vendor: Update for agent tracing and fix issues

Updated the agent vendoring for `StartTracing` and `StopTracing`. This
only changed a single file - the auto-generated gRPC protocol
buffer file.

This change resolves four vendoring issues:

- The github.com/kubernetes-incubator/cri-o project was renamed to
  github.com/cri-o/cri-o. Although github redirects, `dep` complains that
  it cannot find the old `github.com/kubernetes-incubator/cri-o` files
  under `vendor/` so remove the old config, relying on the existing (and
  in other respects identical) `dep` config.

- There was a stale dependency on `github.com/clearcontainers/proxy`
  which should have been removed when the Clear Containers code was
  excised.

- The latest version of the agent code vendored into the runtime prior
  to this commit was a merge commit (commit
  `48dd1c031530fce9bf16b0f6a7305979cedd8fc9`). This somehow confused `dep`
  which did *not* correctly pull in the latest version of the
  auto-generated gRPC code
  (`vendor/github.com/kata-containers/agent/protocols/grpc/agent.pb.go`).
  This is clear because commit `48dd1c031530fce9bf16b0f6a7305979cedd8fc9`
  is newer than the agent commit that introduced the `StartTracing` and
  `StopTracing` APIs (`00cf907afcb7c8e56f077cf45ae3615f612fdc9d`).

  Resolving the other two issues above seems to have resolved this issue
  as the correct version of this file has now been included in the
  vendoring, however note there is no change to the `dep` files as this
  version of `agent.pb.go` should already have been included (!)

- Updating `agent.pb.go` also removed the `AddInterface` and
  `RemoveInterface` API calls which should again also have been removed
  already.

  Updated tests to remove these redundant calls.

Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
This commit is contained in:
James O. D. Hunt 2019-04-24 17:57:07 +01:00
parent b309dc5480
commit b573d9bcb9
13 changed files with 488 additions and 1948 deletions

62
Gopkg.lock generated
View File

@ -2,7 +2,7 @@
[[projects]]
digest = "1:79896046d0807ae89b74ae106b6cb0b346c201c02fc57b7c56017edad7493a61"
digest = "1:5d72bbcc9c8667b11c3dc3cbe681c5a6f71e5096744c0bf7726ab5c6425d5dc4"
name = "github.com/BurntSushi/toml"
packages = ["."]
pruneopts = "NUT"
@ -10,7 +10,7 @@
version = "v0.3.1"
[[projects]]
digest = "1:26b14a6dc72ace253599e969997d5ecf2143c63833c015179786bc756c76eaa4"
digest = "1:2be791e7b333ff7c06f8fb3dc18a7d70580e9399dbdffd352621d067ff260b6e"
name = "github.com/Microsoft/go-winio"
packages = ["."]
pruneopts = "NUT"
@ -18,7 +18,7 @@
version = "v0.4.12"
[[projects]]
digest = "1:e4eec8e05fe8611837a9b34a787cf9c714a2fd9228a0a1f41dd2ccccbaa21b7e"
digest = "1:a8e16b4caf3575365c9aa3380d9418f31dd0b810596faebfe3a15c37fabeee4a"
name = "github.com/Microsoft/hcsshim"
packages = [
".",
@ -65,16 +65,6 @@
revision = "ccb8e960c48f04d6935e72476ae4a51028f9e22f"
version = "v9"
[[projects]]
digest = "1:f1bb062def4356e0ffacbf80952a122489df3d26887249a6d351f5b3c98d4c16"
name = "github.com/clearcontainers/proxy"
packages = [
"api",
"client",
]
pruneopts = "NUT"
revision = "1d2a6a3ea132a86abd0731408b7dc34f2fc17d55"
[[projects]]
branch = "master"
digest = "1:8ecb89af7dfe3ac401bdb0c9390b134ef96a97e85f732d2b0604fb7b3977839f"
@ -99,7 +89,7 @@
revision = "0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f"
[[projects]]
digest = "1:c572858cf95490994cee8faa84a57a8942f735e1a8b6a5a7876d13192754c05e"
digest = "1:b1ddab63ebf3a38cdc2a80fa1f00c45e8dc98e27387968ccc0e5275a43f6cb5e"
name = "github.com/containerd/containerd"
packages = [
"api/events",
@ -120,7 +110,7 @@
revision = "f05672357f56f26751a521175c5a96fc21fa8603"
[[projects]]
digest = "1:4f06807f78ebb5fd6d5fcd539885c0a0be60732eda47189a7feb486ff60a519d"
digest = "1:e7c346f795db5a431ca8bd284faed7aa5b4d544ba6538b20a39b968473f47774"
name = "github.com/containerd/cri-containerd"
packages = [
"pkg/annotations",
@ -216,7 +206,7 @@
version = "v0.3.3"
[[projects]]
digest = "1:2cbc5d9ad66b4eb1e82862757985de8c24d8ca299500e669998694329d05bfc9"
digest = "1:351337e3b022de09e72306f1f9711314cc4bd407c15e8d328e218c655fd55731"
name = "github.com/firecracker-microvm/firecracker-go-sdk"
packages = [
"client",
@ -228,7 +218,7 @@
[[projects]]
branch = "master"
digest = "1:e30aea4f7e276dc80a7041b9e436b45a4c6636e5ba554de835b07beb0f97cc74"
digest = "1:ce0cdcf4a121add67d3c6f7cc08e6233275d0f417852f025b790d35da88fab10"
name = "github.com/globalsign/mgo"
packages = [
"bson",
@ -245,7 +235,7 @@
revision = "20b96f641a5ea98f2f8619ff4f3e061cff4833bd"
[[projects]]
digest = "1:5b7a60e28d9315ba79fb73e6294e5823997673ee64797d28ba2dc7bf71dc6ba6"
digest = "1:e101aa2e25fac7e82ba4d2f66807eedd4bcf11abc5afcb4a4629a88f9a652b84"
name = "github.com/go-openapi/analysis"
packages = [
".",
@ -288,7 +278,7 @@
version = "v0.18.0"
[[projects]]
digest = "1:36b4e8fb9b6f5896fe776b279a6e3a4115ab7d0258d0e0d2ac9c6c58e12531c7"
digest = "1:757a8958779fedcfddafb3ac93f707876db7b4fbc71b76fbc25450b3f057025e"
name = "github.com/go-openapi/runtime"
packages = [
".",
@ -345,7 +335,7 @@
version = "v5.0.1"
[[projects]]
digest = "1:34e8cbba4f0ad2eeda81c98d3f53af4c5862518ec0ebae38730fc36f8a7705f0"
digest = "1:0dfc35f448d29c2ff6a29fb3a6643f44175dc2a07925b1add2dea74e1dd6bf8d"
name = "github.com/gogo/protobuf"
packages = [
"gogoproto",
@ -358,7 +348,7 @@
revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02"
[[projects]]
digest = "1:a8b59d8995b50db3b206d9160817e00aace183e456cb60abf5157de16d12e3c9"
digest = "1:2d0636a8c490d2272dd725db26f74a537111b99b9dbdda0d8b98febe63702aa4"
name = "github.com/golang/protobuf"
packages = [
"proto",
@ -405,16 +395,9 @@
pruneopts = "NUT"
revision = "48dd1c031530fce9bf16b0f6a7305979cedd8fc9"
[[projects]]
digest = "1:04054595e5c5a35d1553a7f3464d18577caf597445d643992998643df56d4afd"
name = "github.com/kubernetes-incubator/cri-o"
packages = ["pkg/annotations"]
pruneopts = "NUT"
revision = "3394b3b2d6af0e41d185bb695c6378be5dd4d61d"
[[projects]]
branch = "master"
digest = "1:ebd709f6c64e850ee37ffd662604b647934ba1b7da39c7ba26381d634a4b6d4d"
digest = "1:84a5a2b67486d5d67060ac393aa255d05d24ed5ee41daecd5635ec22657b6492"
name = "github.com/mailru/easyjson"
packages = [
"buffer",
@ -447,7 +430,7 @@
version = "v1.0.0-rc1"
[[projects]]
digest = "1:d4dcb47c4324ed0af861eda17778f56229d44422819770972183bee0217f9cff"
digest = "1:26537bc93f1e164bbc305117029de9933656ff81c4549609939212aca20a4710"
name = "github.com/opencontainers/runc"
packages = [
"libcontainer/configs",
@ -467,7 +450,7 @@
revision = "5806c35637336642129d03657419829569abc5aa"
[[projects]]
digest = "1:7fea98b6541d058ba0ae5496d57d420d396a3f121a0aec64b4ec2171b0a93846"
digest = "1:7da29c22bcc5c2ffb308324377dc00b5084650348c2799e573ed226d8cc9faf0"
name = "github.com/opentracing/opentracing-go"
packages = [
".",
@ -518,7 +501,7 @@
version = "v0.9.0"
[[projects]]
digest = "1:e2930b698575a7f45df1eaa5473c76109b04a87d6a464e674a68f9c1dff244a1"
digest = "1:432ba4d123dc14d6e3b71ca22051bd1a5aa20a8e466e47edabd9af46405c5cfb"
name = "github.com/sirupsen/logrus"
packages = [
".",
@ -535,7 +518,7 @@
revision = "890a5c3458b43e6104ff5da8dfa139d013d77544"
[[projects]]
digest = "1:d43a3612c85e592ffcefdbc426d3fc0bdbc71435c930664bef8c36034181d681"
digest = "1:87dee780f88f86f300bbd90116e933347cf4a3c65c1960072d412597a8896d50"
name = "github.com/uber/jaeger-client-go"
packages = [
".",
@ -576,7 +559,7 @@
revision = "ac249472b7de27a9e8990819566d9be95ab5b816"
[[projects]]
digest = "1:e53b4392978149151080be2de940b1cfbb542c3b2bc3281e091678a3626397f8"
digest = "1:51b28ecbdddc7e0260899b64d8cf13343bb8f66b4b00585b46c775509755095a"
name = "github.com/vishvananda/netlink"
packages = [
".",
@ -601,7 +584,7 @@
revision = "8dd112bcdc25174059e45e07517d9fc663123347"
[[projects]]
digest = "1:5985d67e107c875e2584b5a65f1590adee7677a4e44eb7e62cd54c7709abba4a"
digest = "1:b20c63a56900e442d5f435613fefc9392cbe8849467510fcc3869dbdad9441bb"
name = "golang.org/x/net"
packages = [
"context",
@ -616,7 +599,7 @@
revision = "a8b9294777976932365dabb6640cf1468d95c70f"
[[projects]]
digest = "1:bfb083c1c1ae3c793c66773f32fa2f5934241d8c6327636f4761f269d018a171"
digest = "1:2fd19a8bed3f4ba8e3b26620f114efec5f39c7b02635a89a915b1cbaefeab5ff"
name = "golang.org/x/sys"
packages = [
"unix",
@ -626,7 +609,7 @@
revision = "1d2aa6dbdea45adaaebb9905d0666e4537563829"
[[projects]]
digest = "1:4e48d0d8df75f1bd0a0afe837599fc9ad96b59eecdd1900fc0dcceccaa5fdffc"
digest = "1:e33513a825fcd765e97b5de639a2f7547542d1a8245df0cef18e1fd390b778a9"
name = "golang.org/x/text"
packages = [
"collate",
@ -658,7 +641,7 @@
revision = "5fe7a883aa19554f42890211544aa549836af7b7"
[[projects]]
digest = "1:c09d7ef1564ca6aee8193b8b9d2d831cb69d29581f53b1b1e6331142d07fddbd"
digest = "1:3d43152515ea791363eb0d1d21378fbf70e7df4a3954fd315898532cf5e64a8c"
name = "google.golang.org/grpc"
packages = [
".",
@ -701,8 +684,6 @@
analyzer-version = 1
input-imports = [
"github.com/BurntSushi/toml",
"github.com/clearcontainers/proxy/api",
"github.com/clearcontainers/proxy/client",
"github.com/containerd/cgroups",
"github.com/containerd/containerd/api/events",
"github.com/containerd/containerd/api/types",
@ -735,7 +716,6 @@
"github.com/kata-containers/agent/pkg/types",
"github.com/kata-containers/agent/protocols/client",
"github.com/kata-containers/agent/protocols/grpc",
"github.com/kubernetes-incubator/cri-o/pkg/annotations",
"github.com/mitchellh/mapstructure",
"github.com/opencontainers/runc/libcontainer/configs",
"github.com/opencontainers/runc/libcontainer/specconv",

View File

@ -1,7 +1,3 @@
[[constraint]]
name = "github.com/clearcontainers/proxy"
revision = "1d2a6a3ea132a86abd0731408b7dc34f2fc17d55"
[[constraint]]
name = "github.com/containernetworking/plugins"
revision = "7f98c94613021d8b57acfa1a2f0c8d0f6fd7ae5a"

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -1,84 +0,0 @@
// Copyright (c) 2017 Intel Corporation
//
// 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 api defines the API cc-proxy exposes to clients (processes
// connecting to the proxy AF_UNIX socket).
//
// This package contains the low level definitions of the protocol, frame
// structure and the various payloads that can be sent and received.
//
// The proxy protocol is composed of commands, responses and notifications.
// They all share the same frame structure: a header followed by an optional
// payload.
//
// • Commands are always initiated by a client, never by the proxy itself.
//
// • Responses are sent by the proxy to acknowledge commands.
//
// • Notifications are sent by either the proxy or clients and do not generate
// responses.
//
// Frame Structure
//
// The frame format is illustrated below:
//
// 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
// 0 1 2 3 4 5 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// ┌───────────────────────────┬───────────────┬───────────────┐
// │ Version │ Header Length │ Reserved │
// ├───────────────────────────┼─────┬─┬───────┼───────────────┤
// │ Reserved │ Res.│E│ Type │ Opcode │
// ├───────────────────────────┴─────┴─┴───────┴───────────────┤
// │ Payload Length │
// ├───────────────────────────────────────────────────────────┤
// │ │
// │ Payload │
// │ │
// │ (variable length, optional and opcode-specific) │
// │ │
// └───────────────────────────────────────────────────────────┘
//
// All header fields are encoded in network order (big endian).
//
// • Version (16 bits) is the proxy protocol version. See api.Version for
// details about what information it encodes.
//
// • Header Length (8 bits) is the length of the header in number of 32-bit
// words. Header Length is greater or equal to 3 (12 bytes).
//
// • Type (4 bits) is the frame type: command (0x0), response (0x1),
// stream (0x2) or notification (0x3).
//
// • Opcode (8 bits) specifies the kind of command, response, stream or
// notification this frame represents. In conjunction with Type, this field
// will dictate the payload content.
//
// • E, Error. This flag is set when a response returns an error. Currently
// Error can ony be set in response frames.
//
// • Payload Length (32 bits) is in bytes.
//
// • Payload is optional data that can be sent with the various frames.
// Commands, responses and notifications usually encode their payloads in JSON
// while stream frames have raw data payloads.
//
// • Reserved fields are reserved for future use and must be zeroed.
//
// Frame Size and Header Length
//
// The full size of a frame is (Header Length + Payload Length). The Payload
// starts at offset Header Length from the start of the frame.
//
// It is guaranteed that future header sizes will be at least 12 bytes.
package api

View File

@ -1,235 +0,0 @@
// Copyright (c) 2017 Intel Corporation
//
// 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 api
import (
"encoding/json"
)
// Version encodes the proxy protocol version.
//
// List of changes:
//
// • version 2: initial version released with Clear Containers 3.0
//
// ⚠⚠⚠ backward incompatible with version 1 ⚠⚠⚠
//
// List of changes:
//
// • Changed the frame header to include additional fields: version,
// header length, type and opcode.
// • Added a log messages for clients to insert log entries to the
// consolidated proxy log.
//
// • version 1: initial version released with Clear Containers 2.1
const Version = 2
// FrameType is the type of frame and is part of the frame header.
type FrameType int
const (
// TypeCommand is a command from a client to the proxy.
TypeCommand FrameType = iota
// TypeResponse is a command response back from the proxy to a client.
TypeResponse
// TypeStream is a stream of data from a client to the proxy. Streams
// are to be forwarded onto the VM agent.
TypeStream
// TypeNotification is a notification sent by either the proxy or
// clients. Notifications are one way only and do not prompt a
// response.
TypeNotification
// TypeMax is the number of types.
TypeMax
)
const unknown = "unknown"
// String implements Stringer for FrameType.
func (t FrameType) String() string {
switch t {
case TypeCommand:
return "command"
case TypeResponse:
return "response"
case TypeStream:
return "stream"
case TypeNotification:
return "notification"
default:
return unknown
}
}
// Command is the kind of command being sent. In the frame header, Opcode must
// have one of these values when Type is api.TypeCommand.
type Command int
const (
// CmdRegisterVM registers a new VM/POD.
CmdRegisterVM Command = iota
// CmdUnregisterVM unregisters a VM/POD.
CmdUnregisterVM
// CmdAttachVM attaches to a registered VM.
CmdAttachVM
// CmdHyper sends a hyperstart command through the proxy.
CmdHyper
// CmdConnectShim identifies the client as a shim.
CmdConnectShim
// CmdDisconnectShim unregisters a shim. DisconnectShim is a bit
// special and doesn't send a Response back but closes the connection.
CmdDisconnectShim
// CmdSignal sends a signal to the process inside the VM. A client
// needs to be connected as a shim before it can issue that command.
CmdSignal
// CmdMax is the number of commands.
CmdMax
)
// String implements Stringer for Command.
func (t Command) String() string {
switch t {
case CmdRegisterVM:
return "RegisterVM"
case CmdUnregisterVM:
return "UnregisterVM"
case CmdAttachVM:
return "AttachVM"
case CmdHyper:
return "Hyper"
case CmdConnectShim:
return "ConnectShim"
case CmdDisconnectShim:
return "DisconnectShim"
case CmdSignal:
return "Signal"
default:
return unknown
}
}
// Stream is the kind of stream being sent. In the frame header, Opcode must
// have one of the these values when Type is api.TypeStream.
type Stream int
const (
// StreamStdin is a stream conveying stdin data.
StreamStdin Stream = iota
// StreamStdout is a stream conveying stdout data.
StreamStdout
// StreamStderr is a stream conveying stderr data.
StreamStderr
// StreamLog is a stream conveying structured logs messages. Each Log frame
// contains a JSON object which fields are the structured log. By convention
// it would be nice to have a few common fields in log entries to ease
// post-processing. See the LogEntry payload for details.
StreamLog
// StreamMax is the number of stream types.
StreamMax
)
// String implements Stringer for Stream.
func (s Stream) String() string {
switch s {
case StreamStdin:
return "stdin"
case StreamStdout:
return "stdout"
case StreamStderr:
return "stderr"
case StreamLog:
return "log"
default:
return unknown
}
}
// Notification is the kind of notification being sent. In the frame header,
// Opcode must have one of the these values when Type is api.TypeNotification.
type Notification int
const (
// NotificationProcessExited is sent to signal a process in the VM has exited.
NotificationProcessExited = iota
// NotificationMax is the number of notification types.
NotificationMax
)
// String implements Stringer for Notification.
func (n Notification) String() string {
switch n {
case NotificationProcessExited:
return "ProcessExited"
default:
return unknown
}
}
// FrameHeader is the header of a Frame.
type FrameHeader struct {
Version int
// HeaderLength in the size of the header in bytes (the on-wire
// HeaderLength is in number of 32-bits words tough).
HeaderLength int
Type FrameType
Opcode int
PayloadLength int
InError bool
}
// Frame is the basic communication unit with the proxy.
type Frame struct {
Header FrameHeader
Payload []byte
}
// NewFrame creates a new Frame with type t, operand op and given payload.
func NewFrame(t FrameType, op int, payload []byte) *Frame {
return &Frame{
Header: FrameHeader{
Version: Version,
HeaderLength: minHeaderLength,
Type: t,
Opcode: op,
PayloadLength: len(payload),
},
Payload: payload,
}
}
// NewFrameJSON creates a new Frame with type t, operand op and given payload.
// The payload structure is marshalled into JSON.
func NewFrameJSON(t FrameType, op int, payload interface{}) (*Frame, error) {
var data []byte
if payload != nil {
var err error
if data, err = json.Marshal(payload); err != nil {
return nil, err
}
}
return &Frame{
Header: FrameHeader{
Version: Version,
HeaderLength: minHeaderLength,
Type: t,
Opcode: op,
PayloadLength: len(data),
},
Payload: data,
}, nil
}

View File

@ -1,183 +0,0 @@
// Copyright (c) 2016,2017 Intel Corporation
//
// 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 api
import (
"encoding/json"
)
// The RegisterVM payload is issued first after connecting to the proxy socket.
// It is used to let the proxy know about a new container on the system along
// with the paths go hyperstart's command and I/O channels (AF_UNIX sockets).
//
// Console can be used to indicate the path of a socket linked to the VM
// console. The proxy can output this data when asked for verbose output.
//
// {
// "containerId": "756535dc6e9ab9b560f84c8...",
// "ctlSerial": "/tmp/sh.hyper.channel.0.sock",
// "ioSerial": "/tmp/sh.hyper.channel.1.sock",
// "numIOStreams: 1
// }
type RegisterVM struct {
ContainerID string `json:"containerId"`
CtlSerial string `json:"ctlSerial"`
IoSerial string `json:"ioSerial"`
Console string `json:"console,omitempty"`
// NumIOStreams asks for a number of I/O tokens. An I/O token
// represents the communication between a container process inside
// the VM and a shim process outside the VM. This communication
// includes I/O streams (stdin, out, err) but also signals, exit
// status, ...
// The response frame will contain NumIOStreams I/O tokens.
NumIOStreams int `json:"numIOStreams,omitempty"`
}
// IOResponse is the response data in RegisterVMResponse and AttachVMResponse
// when the client is asking for I/O tokens from the proxy (NumIOStreams > 0).
type IOResponse struct {
// URL is the URL a shim process should connect to in order to initiate
// the I/O communication with the process inside the VM
URL string
// IOTokens is a array of I/O tokens of length NumIOStreams. See
// RegisterVM for some details on I/O tokens.
Tokens []string `json:"tokens"`
}
// RegisterVMResponse is the result from a successful RegisterVM.
//
// {
// "io": {
// "url": "unix:///run/clearcontainers/proxy.sock",
// "tokens": [
// "bwgxfmQj9uG3YCsFHrvontwDw41CJJ76Y7qVt4Bi9wc="
// ]
// }
// }
type RegisterVMResponse struct {
// IO contains the proxy answer when asking for I/O tokens.
IO IOResponse `json:"io,omitempty"`
}
// The AttachVM payload can be used to associate clients to an already known
// VM. AttachVM cannot be issued if a RegisterVM for this container hasn't been
// issued beforehand.
//
// {
// "containerId": "756535dc6e9ab9b560f84c8...".
// "numIOStreams: 1
// }
type AttachVM struct {
ContainerID string `json:"containerId"`
// NumIOStreams asks for a number of I/O tokens. See RegisterVM for
// some details on I/O tokens.
NumIOStreams int `json:"numIOStreams,omitempty"`
}
// AttachVMResponse is the result from a successful AttachVM.
//
// {
// "io": {
// "url": "unix:///run/clearcontainers/proxy.sock",
// "tokens": [
// "bwgxfmQj9uG3YCsFHrvontwDw41CJJ76Y7qVt4Bi9wc="
// ]
// }
// }
type AttachVMResponse struct {
// IO contains the proxy answer when asking for I/O tokens.
IO IOResponse `json:"io,omitempty"`
}
// The UnregisterVM payload does the opposite of what RegisterVM does,
// indicating to the proxy it should release resources created by RegisterVM
// for the container identified by containerId.
//
// {
// "containerId": "756535dc6e9ab9b560f84c8..."
// }
type UnregisterVM struct {
ContainerID string `json:"containerId"`
}
// The Hyper payload will forward an hyperstart command to hyperstart.
//
// Note: the newcontainer and execmd hyperstart commands start one or more
// processes. When sending those commands, tokens acquired through either
// RegisterVM or AttachVM need to be sent along in the tokens array. The number
// of tokens sent has to match the number of processes to be started.
//
// {
// "hyperName": "newcontainer",
// "tokens": [
// "bwgxfmQj9uG3YCsFHrvontwDw41CJJ76Y7qVt4Bi9wc="
// ],
// "data": {
// "id": "756535dc6e9ab9b560f84c8...",
// "rootfs": "/foo/bar",
// ...
// }
// }
// }
type Hyper struct {
HyperName string `json:"hyperName"`
Tokens []string `json:"tokens"`
Data json.RawMessage `json:"data,omitempty"`
}
// ConnectShim identifies a shim against the proxy. A shim process is a process
// running on host shadowing a container process running inside the VM. A shim
// will forward stdin and signals to the process inside the VM and will receive
// stdout, stderr and the exit status.
type ConnectShim struct {
// Token is id corresponding to the process the shim wants to handle
// the I/O streams, signals, exit status for. Tokens are allocated with
// a call to RegisterVM or AttachVM.
Token string `json:"token"`
}
// DisconnectShim unregister a shim from the proxy.
type DisconnectShim struct {
}
// Signal is used to send signals to the container process inside the VM. This
// payload is only valid after a successful ConnectShim.
type Signal struct {
SignalNumber int `json:"signalNumber"`
// Columns is only valid for SIGWINCH and is the new number of columns of
// the terminal.
Columns int `json:"columns,omitempty"`
// Rows is only valid for SIGWINCH and is the new number of rows of the
// terminal.
Rows int `json:"rows,omitempty"`
}
// ErrorResponse is the payload send in Responses where the Error flag is set.
type ErrorResponse struct {
Message string `json:"msg"`
}
// LogEntry is the payload for the StreamLog data.
type LogEntry struct {
// Source is the source of the log entry. One of "shim" or "runtime".
Source string `json:"source"`
// ContainerID is the ID of the container the log entry is for (optional).
ContainerID string `json:"containerId,omitempty"`
// Level is the verbosity level of the log entry. One of "debug", "info", "warn"
// or "error".
Level string `json:"level"`
// Message is the log message
Message string `json:"msg"`
}

View File

@ -1,213 +0,0 @@
// Copyright (c) 2016 Intel Corporation
//
// 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 api
import (
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"io"
)
// minHeaderLength is the length of the header in the version 2 of protocol.
// It is guaranteed later versions will have a header at least that big.
const minHeaderLength = 12 // in bytes
// A Request is a JSON message sent from a client to the proxy. This message
// embed a payload identified by "id". A payload can have data associated with
// it. It's useful to think of Request as an RPC call with "id" as function
// name and "data" as arguments.
//
// The list of possible payloads are documented in this package.
//
// Each Request has a corresponding Response message sent back from the proxy.
type Request struct {
ID string `json:"id"`
Data json.RawMessage `json:"data,omitempty"`
}
// A Response is a JSON message sent back from the proxy to a client after a
// Request has been issued. The Response holds the result of the Request,
// including its success state and optional data. It's useful to think of
// Response as the result of an RPC call with ("success", "error") describing
// if the call has been successful and "data" holding the optional results.
type Response struct {
Success bool `json:"success"`
Error string `json:"error,omitempty"`
Data map[string]interface{} `json:"data,omitempty"`
}
// Offsets (in bytes) of frame headers fields.
const (
versionOffset = 0
headerLengthOffset = 2
typeOffset = 6
flagsOffset = 6
opcodeOffset = 7
payloadLengthOffset = 8
)
// Size (in bytes) of frame header fields (when larger than 1 byte).
const (
versionSize = 2
payloadLengthSize = 4
)
// Masks needed to extract fields
const (
typeMask = 0x0f
flagsMask = 0xf0
)
func maxOpcodeForFrameType(t FrameType) int {
switch t {
default:
fallthrough
case TypeCommand:
return int(CmdMax)
case TypeResponse:
return int(CmdMax)
case TypeStream:
return int(StreamMax)
case TypeNotification:
return int(NotificationMax)
}
}
// ReadFrame reads a full frame (header and payload) from r.
func ReadFrame(r io.Reader) (*Frame, error) {
// Read the header.
buf := make([]byte, minHeaderLength)
n, err := r.Read(buf)
if err != nil {
return nil, err
}
if n != minHeaderLength {
return nil, errors.New("frame: couldn't read the full header")
}
// Decode it.
frame := &Frame{}
header := &frame.Header
header.Version = int(binary.BigEndian.Uint16(buf[versionOffset : versionOffset+versionSize]))
if header.Version < 2 || header.Version > Version {
return nil, fmt.Errorf("frame: bad version %d", header.Version)
}
header.HeaderLength = int(buf[headerLengthOffset]) * 4
header.Type = FrameType(buf[typeOffset] & typeMask)
flags := buf[flagsOffset] & flagsMask
if flags&flagInError != 0 {
header.InError = true
}
if header.Type >= TypeMax {
return nil, fmt.Errorf("frame: bad type %s", header.Type)
}
header.Opcode = int(buf[opcodeOffset])
if header.Opcode >= maxOpcodeForFrameType(header.Type) {
return nil, fmt.Errorf("frame: bad opcode (%d) for type %s", header.Opcode,
header.Type)
}
header.PayloadLength = int(binary.BigEndian.Uint32(buf[payloadLengthOffset : payloadLengthOffset+payloadLengthSize]))
// Read the payload.
received := 0
need := header.HeaderLength - minHeaderLength + header.PayloadLength
payload := make([]byte, need)
for received < need {
n, err := r.Read(payload[received:need])
if err != nil {
return nil, err
}
received += n
}
// Skip the bytes part of a bigger header than expected to just keep
// the payload.
frame.Payload = payload[header.HeaderLength-minHeaderLength : need]
return frame, nil
}
const (
flagInError = 1 << (4 + iota)
)
// WriteFrame writes a frame into w.
//
// Note that frame.Header.PayloadLength dictates the amount of data of
// frame.Payload to write, so frame.Header.Payload must be less or equal to
// len(frame.Payload).
func WriteFrame(w io.Writer, frame *Frame) error {
header := &frame.Header
if len(frame.Payload) < header.PayloadLength {
return fmt.Errorf("frame: bad payload length %d",
header.PayloadLength)
}
// Prepare the header.
len := minHeaderLength + header.PayloadLength
buf := make([]byte, len)
binary.BigEndian.PutUint16(buf[versionOffset:versionOffset+versionSize], uint16(header.Version))
buf[headerLengthOffset] = byte(header.HeaderLength / 4)
flags := byte(0)
if frame.Header.InError {
flags |= flagInError
}
buf[typeOffset] = flags | byte(header.Type)&typeMask
buf[opcodeOffset] = byte(header.Opcode)
binary.BigEndian.PutUint32(buf[payloadLengthOffset:payloadLengthOffset+payloadLengthSize],
uint32(header.PayloadLength))
// Write payload if needed
if header.PayloadLength > 0 {
copy(buf[minHeaderLength:], frame.Payload[0:header.PayloadLength])
}
n, err := w.Write(buf)
if err != nil {
return err
}
if n != len {
return errors.New("frame: couldn't write frame")
}
return nil
}
// WriteCommand is a convenience wrapper around WriteFrame to send commands.
func WriteCommand(w io.Writer, op Command, payload []byte) error {
return WriteFrame(w, NewFrame(TypeCommand, int(op), payload))
}
// WriteResponse is a convenience wrapper around WriteFrame to send responses.
func WriteResponse(w io.Writer, op Command, inError bool, payload []byte) error {
frame := NewFrame(TypeResponse, int(op), payload)
frame.Header.InError = inError
return WriteFrame(w, frame)
}
// WriteStream is a convenience wrapper around WriteFrame to send stream packets.
func WriteStream(w io.Writer, op Stream, payload []byte) error {
return WriteFrame(w, NewFrame(TypeStream, int(op), payload))
}
// WriteNotification is a convenience wrapper around WriteFrame to send notifications.
func WriteNotification(w io.Writer, op Notification, payload []byte) error {
return WriteFrame(w, NewFrame(TypeNotification, int(op), payload))
}

View File

@ -1,410 +0,0 @@
// Copyright (c) 2016 Intel Corporation
//
// 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 client
import (
"encoding/json"
"errors"
"fmt"
"net"
"syscall"
"github.com/clearcontainers/proxy/api"
)
// The Client struct can be used to issue proxy API calls with a convenient
// high level API.
type Client struct {
conn net.Conn
}
// NewClient creates a new client object to communicate with the proxy using
// the connection conn. The user should call Close() once finished with the
// client object to close conn.
func NewClient(conn net.Conn) *Client {
return &Client{
conn: conn,
}
}
// Close a client, closing the underlying AF_UNIX socket.
func (client *Client) Close() {
client.conn.Close()
}
func (client *Client) sendCommandFull(cmd api.Command, payload interface{},
waitForResponse bool) (*api.Frame, error) {
var data []byte
var frame *api.Frame
var err error
if payload != nil {
if data, err = json.Marshal(payload); err != nil {
return nil, err
}
}
if err := api.WriteCommand(client.conn, cmd, data); err != nil {
return nil, err
}
if !waitForResponse {
return nil, nil
}
if frame, err = api.ReadFrame(client.conn); err != nil {
return nil, err
}
if cmd == api.CmdSignal {
payloadSignal, ok := payload.(*api.Signal)
if !ok {
return nil, err
}
if payloadSignal.SignalNumber == int(syscall.SIGKILL) ||
payloadSignal.SignalNumber == int(syscall.SIGTERM) {
if frame.Header.Type != api.TypeNotification {
return nil, fmt.Errorf("unexpected frame type %v", frame.Header.Type)
}
if frame, err = api.ReadFrame(client.conn); err != nil {
return nil, err
}
}
}
if frame.Header.Type != api.TypeResponse {
return nil, fmt.Errorf("unexpected frame type %v", frame.Header.Type)
}
if frame.Header.Opcode != int(cmd) {
return nil, fmt.Errorf("unexpected opcode %v", frame.Header.Opcode)
}
return frame, nil
}
func (client *Client) sendCommand(cmd api.Command, payload interface{}) (*api.Frame, error) {
return client.sendCommandFull(cmd, payload, true)
}
func (client *Client) sendCommandNoResponse(cmd api.Command, payload interface{}) error {
_, err := client.sendCommandFull(cmd, payload, false)
return err
}
func errorFromResponse(resp *api.Frame) error {
// We should always have an error with the response, but better safe
// than sorry.
if !resp.Header.InError {
return nil
}
decoded := api.ErrorResponse{}
if err := json.Unmarshal(resp.Payload, &decoded); err != nil {
return err
}
if decoded.Message == "" {
return errors.New("unknown error")
}
return errors.New(decoded.Message)
}
func unmarshalResponse(resp *api.Frame, decoded interface{}) error {
if len(resp.Payload) == 0 {
return nil
}
if err := json.Unmarshal(resp.Payload, decoded); err != nil {
return err
}
return nil
}
// RegisterVMOptions holds extra arguments one can pass to the RegisterVM
// function.
//
// See the api.RegisterVM payload for more details.
type RegisterVMOptions struct {
Console string
NumIOStreams int
}
// RegisterVMReturn contains the return values from RegisterVM.
//
// See the api.RegisterVM and api.RegisterVMResponse payloads.
type RegisterVMReturn api.RegisterVMResponse
// RegisterVM wraps the api.RegisterVM payload.
//
// See payload description for more details.
func (client *Client) RegisterVM(containerID, ctlSerial, ioSerial string,
options *RegisterVMOptions) (*RegisterVMReturn, error) {
payload := api.RegisterVM{
ContainerID: containerID,
CtlSerial: ctlSerial,
IoSerial: ioSerial,
}
if options != nil {
payload.Console = options.Console
payload.NumIOStreams = options.NumIOStreams
}
resp, err := client.sendCommand(api.CmdRegisterVM, &payload)
if err != nil {
return nil, err
}
if err := errorFromResponse(resp); err != nil {
return nil, err
}
decoded := RegisterVMReturn{}
err = unmarshalResponse(resp, &decoded)
return &decoded, err
}
// AttachVMOptions holds extra arguments one can pass to the AttachVM function.
//
// See the api.AttachVM payload for more details.
type AttachVMOptions struct {
NumIOStreams int
}
// AttachVMReturn contains the return values from AttachVM.
//
// See the api.AttachVM and api.AttachVMResponse payloads.
type AttachVMReturn api.AttachVMResponse
// AttachVM wraps the api.AttachVM payload.
//
// See the api.AttachVM payload description for more details.
func (client *Client) AttachVM(containerID string, options *AttachVMOptions) (*AttachVMReturn, error) {
payload := api.AttachVM{
ContainerID: containerID,
}
if options != nil {
payload.NumIOStreams = options.NumIOStreams
}
resp, err := client.sendCommand(api.CmdAttachVM, &payload)
if err != nil {
return nil, err
}
if err := errorFromResponse(resp); err != nil {
return nil, err
}
decoded := AttachVMReturn{}
err = unmarshalResponse(resp, &decoded)
return &decoded, err
}
// Hyper wraps the Hyper payload (see payload description for more details)
func (client *Client) Hyper(hyperName string, hyperMessage interface{}) ([]byte, error) {
return client.HyperWithTokens(hyperName, nil, hyperMessage)
}
// HyperWithTokens is a Hyper variant where the users can specify a list of I/O tokens.
//
// See the api.Hyper payload description for more details.
func (client *Client) HyperWithTokens(hyperName string, tokens []string, hyperMessage interface{}) ([]byte, error) {
var data []byte
if hyperMessage != nil {
var err error
data, err = json.Marshal(hyperMessage)
if err != nil {
return nil, err
}
}
hyper := api.Hyper{
HyperName: hyperName,
Data: data,
}
if tokens != nil {
hyper.Tokens = tokens
}
resp, err := client.sendCommand(api.CmdHyper, &hyper)
if err != nil {
return nil, err
}
if err = errorFromResponse(resp); err != nil {
return nil, err
}
return resp.Payload, errorFromResponse(resp)
}
// UnregisterVM wraps the api.UnregisterVM payload.
//
// See the api.UnregisterVM payload description for more details.
func (client *Client) UnregisterVM(containerID string) error {
payload := api.UnregisterVM{
ContainerID: containerID,
}
resp, err := client.sendCommand(api.CmdUnregisterVM, &payload)
if err != nil {
return err
}
return errorFromResponse(resp)
}
// ConnectShim wraps the api.CmdConnectShim command and associated
// api.ConnectShim payload.
func (client *Client) ConnectShim(token string) error {
payload := api.ConnectShim{
Token: token,
}
resp, err := client.sendCommand(api.CmdConnectShim, &payload)
if err != nil {
return err
}
return errorFromResponse(resp)
}
// DisconnectShim wraps the api.CmdDisconnectShim command and associated
// api.DisconnectShim payload.
func (client *Client) DisconnectShim() error {
return client.sendCommandNoResponse(api.CmdDisconnectShim, nil)
}
func (client *Client) signal(signal syscall.Signal, columns, rows int) error {
payload := api.Signal{
SignalNumber: int(signal),
Columns: columns,
Rows: rows,
}
resp, err := client.sendCommand(api.CmdSignal, &payload)
if err != nil {
return err
}
return errorFromResponse(resp)
}
// Kill wraps the api.CmdSignal command and can be used by a shim to send a
// signal to the associated process.
func (client *Client) Kill(signal syscall.Signal) error {
return client.signal(signal, 0, 0)
}
// SendTerminalSize wraps the api.CmdSignal command and can be used by a shim
// to send a new signal to the associated process.
func (client *Client) SendTerminalSize(columns, rows int) error {
return client.signal(syscall.SIGWINCH, columns, rows)
}
func (client *Client) sendStream(op api.Stream, data []byte) error {
return api.WriteStream(client.conn, op, data)
}
// SendStdin sends stdin data. This can only be used from shim clients.
func (client *Client) SendStdin(data []byte) error {
return client.sendStream(api.StreamStdin, data)
}
// LogLevel is the severity of log entries.
type LogLevel uint8
const (
// LogLevelDebug is for log messages only useful debugging.
LogLevelDebug LogLevel = iota
// LogLevelInfo is for reporting landmark events.
LogLevelInfo
// LogLevelWarn is for reporting warnings.
LogLevelWarn
// LogLevelError is for reporting errors.
LogLevelError
logLevelMax
)
var levelToString = []string{"debug", "info", "warn", "error"}
// String implements stringer for LogLevel.
func (l LogLevel) String() string {
if l < logLevelMax {
return levelToString[l]
}
return "unknown"
}
// LogSource is the source of log entries
type LogSource uint8
const (
// LogSourceRuntime represents a runtime.
LogSourceRuntime LogSource = iota
// LogSourceShim represents a shim.
LogSourceShim
logSourceMax
)
var sourceToString = []string{"runtime", "shim"}
// String implements stringer for LogSource
func (s LogSource) String() string {
if s < logSourceMax {
return sourceToString[s]
}
return "unknown"
}
// Log sends log entries.
func (client *Client) Log(level LogLevel, source LogSource, containerID string, args ...interface{}) {
payload := api.LogEntry{
Level: level.String(),
Source: source.String(),
ContainerID: containerID,
Message: fmt.Sprint(args...),
}
data, _ := json.Marshal(&payload)
_ = client.sendStream(api.StreamLog, data)
}
// Logf sends log entries.
func (client *Client) Logf(level LogLevel, source LogSource, containerID string, format string, args ...interface{}) {
payload := api.LogEntry{
Level: level.String(),
Source: source.String(),
ContainerID: containerID,
Message: fmt.Sprintf(format, args...),
}
data, _ := json.Marshal(&payload)
_ = client.sendStream(api.StreamLog, data)
}

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,6 @@
package vsock
import (
"errors"
"net"
"os"
"time"
@ -11,31 +10,40 @@ import (
"golang.org/x/sys/unix"
)
var (
// errDeadlinesNotImplemented is returned by the SetDeadline family of methods
// for conn, because access is not yet available to the runtime network poller
// for non-standard sockets types.
// See: https://github.com/golang/go/issues/10565.
errDeadlinesNotImplemented = errors.New("vsock: deadlines not implemented")
)
var _ net.Conn = &conn{}
// A conn is the net.Conn implementation for VM sockets.
type conn struct {
*os.File
file *os.File
localAddr *Addr
remoteAddr *Addr
}
// LocalAddr and RemoteAddr implement the net.Conn interface for conn.
func (c *conn) LocalAddr() net.Addr { return c.localAddr }
func (c *conn) RemoteAddr() net.Addr { return c.remoteAddr }
// Implement net.Conn for type conn.
func (c *conn) LocalAddr() net.Addr { return c.localAddr }
func (c *conn) RemoteAddr() net.Addr { return c.remoteAddr }
func (c *conn) SetDeadline(t time.Time) error { return c.file.SetDeadline(t) }
func (c *conn) SetReadDeadline(t time.Time) error { return c.file.SetReadDeadline(t) }
func (c *conn) SetWriteDeadline(t time.Time) error { return c.file.SetWriteDeadline(t) }
func (c *conn) Read(b []byte) (n int, err error) { return c.file.Read(b) }
func (c *conn) Write(b []byte) (n int, err error) { return c.file.Write(b) }
func (c *conn) Close() error { return c.file.Close() }
// SetDeadline functions implement the net.Conn interface for conn.
func (c *conn) SetDeadline(_ time.Time) error { return errDeadlinesNotImplemented }
func (c *conn) SetReadDeadline(_ time.Time) error { return errDeadlinesNotImplemented }
func (c *conn) SetWriteDeadline(_ time.Time) error { return errDeadlinesNotImplemented }
// newConn creates a conn using an fd with the specified file name, local, and
// remote addresses.
func newConn(cfd fd, file string, local, remote *Addr) (*conn, error) {
// Enable integration with runtime network poller for timeout support
// in Go 1.11+.
if err := cfd.SetNonblock(true); err != nil {
return nil, err
}
return &conn{
file: cfd.NewFile(file),
localAddr: local,
remoteAddr: remote,
}, nil
}
// dialStream is the entry point for DialStream on Linux.
func dialStream(cid, port uint32) (net.Conn, error) {
@ -89,9 +97,6 @@ func dialStreamLinux(cfd fd, cid, port uint32) (net.Conn, error) {
Port: port,
}
return &conn{
File: cfd.NewFile(remoteAddr.fileName()),
localAddr: localAddr,
remoteAddr: remoteAddr,
}, nil
// File name is the name of the local socket.
return newConn(cfd, localAddr.fileName(), localAddr, remoteAddr)
}

View File

@ -11,11 +11,12 @@ import (
type fd interface {
Accept4(flags int) (fd, unix.Sockaddr, error)
Bind(sa unix.Sockaddr) error
Connect(sa unix.Sockaddr) error
Close() error
Connect(sa unix.Sockaddr) error
Getsockname() (unix.Sockaddr, error)
Listen(n int) error
NewFile(name string) *os.File
SetNonblock(nonblocking bool) error
}
var _ fd = &sysFD{}
@ -38,6 +39,7 @@ func (fd *sysFD) Accept4(flags int) (fd, unix.Sockaddr, error) {
func (fd *sysFD) Bind(sa unix.Sockaddr) error { return unix.Bind(fd.fd, sa) }
func (fd *sysFD) Close() error { return unix.Close(fd.fd) }
func (fd *sysFD) Connect(sa unix.Sockaddr) error { return unix.Connect(fd.fd, sa) }
func (fd *sysFD) Getsockname() (unix.Sockaddr, error) { return unix.Getsockname(fd.fd) }
func (fd *sysFD) Listen(n int) error { return unix.Listen(fd.fd, n) }
func (fd *sysFD) NewFile(name string) *os.File { return os.NewFile(uintptr(fd.fd), name) }
func (fd *sysFD) Getsockname() (unix.Sockaddr, error) { return unix.Getsockname(fd.fd) }
func (fd *sysFD) SetNonblock(nonblocking bool) error { return unix.SetNonblock(fd.fd, nonblocking) }

View File

@ -35,11 +35,7 @@ func (l *listener) Accept() (net.Conn, error) {
Port: savm.Port,
}
return &conn{
File: cfd.NewFile(l.addr.fileName()),
localAddr: l.addr,
remoteAddr: remoteAddr,
}, nil
return newConn(cfd, l.addr.fileName(), l.addr, remoteAddr)
}
// listenStream is the entry point for ListenStream on Linux.
@ -87,6 +83,10 @@ func listenStreamLinux(lfd fd, cid, port uint32) (net.Listener, error) {
Port: port,
}
if err := lfd.SetNonblock(true); err != nil {
return nil, err
}
if err := lfd.Bind(sa); err != nil {
return nil, err
}

View File

@ -191,14 +191,6 @@ func (p *gRPCProxy) DestroySandbox(ctx context.Context, req *pb.DestroySandboxRe
return emptyResp, nil
}
func (p *gRPCProxy) AddInterface(ctx context.Context, req *pb.AddInterfaceRequest) (*aTypes.Interface, error) {
return nil, nil
}
func (p *gRPCProxy) RemoveInterface(ctx context.Context, req *pb.RemoveInterfaceRequest) (*aTypes.Interface, error) {
return nil, nil
}
func (p *gRPCProxy) UpdateInterface(ctx context.Context, req *pb.UpdateInterfaceRequest) (*aTypes.Interface, error) {
return &aTypes.Interface{}, nil
}