mirror of
https://github.com/containers/podman.git
synced 2025-06-25 20:26:51 +08:00
fix(deps): update github.com/digitalocean/go-qemu digest to f035778
Signed-off-by: Renovate Bot <bot@renovateapp.com>
This commit is contained in:
4
go.mod
4
go.mod
@ -23,7 +23,7 @@ require (
|
|||||||
github.com/coreos/go-systemd/v22 v22.5.0
|
github.com/coreos/go-systemd/v22 v22.5.0
|
||||||
github.com/coreos/stream-metadata-go v0.4.1
|
github.com/coreos/stream-metadata-go v0.4.1
|
||||||
github.com/cyphar/filepath-securejoin v0.2.3
|
github.com/cyphar/filepath-securejoin v0.2.3
|
||||||
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001
|
github.com/digitalocean/go-qemu v0.0.0-20221209210016-f035778c97f7
|
||||||
github.com/docker/docker v23.0.5+incompatible
|
github.com/docker/docker v23.0.5+incompatible
|
||||||
github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11
|
github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11
|
||||||
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
|
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
|
||||||
@ -87,7 +87,7 @@ require (
|
|||||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
|
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
|
||||||
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 // indirect
|
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1 // indirect
|
github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e // indirect
|
||||||
github.com/disiqueira/gotree/v3 v3.0.2 // indirect
|
github.com/disiqueira/gotree/v3 v3.0.2 // indirect
|
||||||
github.com/docker/distribution v2.8.1+incompatible // indirect
|
github.com/docker/distribution v2.8.1+incompatible // indirect
|
||||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||||
|
13
go.sum
13
go.sum
@ -303,10 +303,10 @@ github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8l
|
|||||||
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1 h1:j6vGflaQ2T7yOWqVgPdiRF73j/U2Zmpbbzab8nyDCRQ=
|
github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e h1:SCnqm8SjSa0QqRxXbo5YY//S+OryeJioe17nK+iDZpg=
|
||||||
github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1/go.mod h1:QS1XzqZLcDniNYrN7EZefq3wIyb/M2WmJbql4ZKoc1Q=
|
github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e/go.mod h1:o129ljs6alsIQTc8d6eweihqpmmrbxZ2g1jhgjhPykI=
|
||||||
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001 h1:WAg57gnaAWWjMAELcwHjc2xy0PoXQ5G+vn3+XS6s1jI=
|
github.com/digitalocean/go-qemu v0.0.0-20221209210016-f035778c97f7 h1:3OVJAbR131SnAXao7c9w8bFlAGH0oa29DCwsa88MJGk=
|
||||||
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001/go.mod h1:IetBE52JfFxK46p2n2Rqm+p5Gx1gpu2hRHsrbnPOWZQ=
|
github.com/digitalocean/go-qemu v0.0.0-20221209210016-f035778c97f7/go.mod h1:K4+o74YGNjOb9N6yyG+LPj1NjHtk+Qz0IYQPvirbaLs=
|
||||||
github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWhkNRq8=
|
github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWhkNRq8=
|
||||||
github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
|
github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
@ -352,7 +352,6 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
|
|||||||
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
|
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
|
||||||
github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01 h1:IeaD1VDVBPlx3viJT9Md8if8IxxJnO+x0JCGb054heg=
|
github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01 h1:IeaD1VDVBPlx3viJT9Md8if8IxxJnO+x0JCGb054heg=
|
||||||
github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52 h1:a4DFiKFJiDRGFD1qIcqGLX/WlUMD9dyLSLDt+9QZgt8=
|
github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52 h1:a4DFiKFJiDRGFD1qIcqGLX/WlUMD9dyLSLDt+9QZgt8=
|
||||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
@ -1019,7 +1018,6 @@ github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
|
|||||||
github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE=
|
github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE=
|
||||||
github.com/ysmood/leakless v0.8.0 h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak=
|
github.com/ysmood/leakless v0.8.0 h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
@ -1146,7 +1144,6 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
@ -1252,7 +1249,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -1345,7 +1341,6 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY
|
|||||||
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
1
vendor/github.com/digitalocean/go-libvirt/.gitignore
generated
vendored
Normal file
1
vendor/github.com/digitalocean/go-libvirt/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.idea/
|
62
vendor/github.com/digitalocean/go-libvirt/.travis.yml
generated
vendored
62
vendor/github.com/digitalocean/go-libvirt/.travis.yml
generated
vendored
@ -1,62 +0,0 @@
|
|||||||
language: go
|
|
||||||
os: linux
|
|
||||||
dist: bionic
|
|
||||||
sudo: require
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.ccache
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "1.15"
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
|
||||||
matrix:
|
|
||||||
- LIBVIRT=2.3.0 EXT=xz
|
|
||||||
- LIBVIRT=3.1.0 EXT=xz
|
|
||||||
- LIBVIRT=5.1.0 EXT=xz
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- go get golang.org/x/lint/golint
|
|
||||||
- go get golang.org/x/tools/cmd/goyacc
|
|
||||||
|
|
||||||
install:
|
|
||||||
# credit here goes to the go-libvirt authors,
|
|
||||||
# see: https://github.com/rgbkrk/libvirt-go/blob/master/.travis.yml
|
|
||||||
- sudo apt-get -qqy build-dep libvirt
|
|
||||||
- sudo apt-get -qqy install curl qemu-system-x86
|
|
||||||
- sudo mkdir -p /usr/src && sudo chown $(id -u) /usr/src
|
|
||||||
- curl -O -s https://libvirt.org/sources/libvirt-${LIBVIRT}.tar.${EXT}
|
|
||||||
- tar -C /usr/src -xf libvirt-${LIBVIRT}.tar.${EXT}
|
|
||||||
- pushd /usr/src/libvirt-${LIBVIRT}
|
|
||||||
- ccache --show-stats
|
|
||||||
- |
|
|
||||||
env PATH=/usr/lib/ccache:$PATH \
|
|
||||||
./configure --prefix=/usr --localstatedir=/var --sysconfdir=/etc \
|
|
||||||
--without-polkit \
|
|
||||||
--without-esx --without-vbox --without-xen --without-libxl --without-lxc \
|
|
||||||
--with-qemu
|
|
||||||
- make
|
|
||||||
- sudo make install
|
|
||||||
- ccache --show-stats
|
|
||||||
- popd
|
|
||||||
- sudo libvirtd -d -l -f libvirtd.conf
|
|
||||||
- sudo virtlogd -d || true
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- go get -d ./...
|
|
||||||
- sudo qemu-img create -f raw -o size=10M /var/lib/libvirt/images/test.raw
|
|
||||||
- sudo virsh define .travis/test-domain.xml
|
|
||||||
- sudo virsh start test
|
|
||||||
- sudo virsh pool-create .travis/test-pool.xml
|
|
||||||
- sudo virsh secret-define .travis/test-secret.xml
|
|
||||||
|
|
||||||
script:
|
|
||||||
- ./scripts/licensecheck.sh
|
|
||||||
- LIBVIRT_SOURCE=/usr/src/libvirt-${LIBVIRT} go generate ./...
|
|
||||||
- go build ./...
|
|
||||||
- golint -set_exit_status ./...
|
|
||||||
- go vet ./...
|
|
||||||
- go test -v -tags=integration ./...
|
|
4
vendor/github.com/digitalocean/go-libvirt/AUTHORS
generated
vendored
4
vendor/github.com/digitalocean/go-libvirt/AUTHORS
generated
vendored
@ -22,3 +22,7 @@ Sylvain Baubeau <sbaubeau@redhat.com>
|
|||||||
David Schneider <dsbrng25b@gmail.com>
|
David Schneider <dsbrng25b@gmail.com>
|
||||||
Alec Hothan <ahothan@gmail.com>
|
Alec Hothan <ahothan@gmail.com>
|
||||||
Akos Varga <vrgakos@gmail.com>
|
Akos Varga <vrgakos@gmail.com>
|
||||||
|
Peter Kurfer <peter.kurfer@gmail.com>
|
||||||
|
Sam Roberts <sroberts@digitalocean.com>
|
||||||
|
Moritz Wanzenböck <moritz.wanzenboeck@linbit.com>
|
||||||
|
Jenni Griesmann <jgriesmann@digitalocean.com>
|
||||||
|
3
vendor/github.com/digitalocean/go-libvirt/CONTRIBUTING.md
generated
vendored
3
vendor/github.com/digitalocean/go-libvirt/CONTRIBUTING.md
generated
vendored
@ -25,6 +25,3 @@ under the "Contributors" section using the format:
|
|||||||
`First Last <email@example.com>`.
|
`First Last <email@example.com>`.
|
||||||
|
|
||||||
Finally, submit a pull request for review!
|
Finally, submit a pull request for review!
|
||||||
|
|
||||||
Questions? Feel free to join us in [`#go-qemu` on freenode](https://webchat.freenode.net/)
|
|
||||||
if you'd like to discuss the project.
|
|
||||||
|
121
vendor/github.com/digitalocean/go-libvirt/README.md
generated
vendored
121
vendor/github.com/digitalocean/go-libvirt/README.md
generated
vendored
@ -1,10 +1,13 @@
|
|||||||
libvirt [](http://godoc.org/github.com/digitalocean/go-libvirt) [](https://travis-ci.org/digitalocean/go-libvirt) [](https://goreportcard.com/report/github.com/digitalocean/go-libvirt)
|
libvirt
|
||||||
|
[](http://godoc.org/github.com/digitalocean/go-libvirt)
|
||||||
|
[](https://github.com/digitalocean/go-libvirt/actions/)
|
||||||
|
[](https://goreportcard.com/report/github.com/digitalocean/go-libvirt)
|
||||||
====
|
====
|
||||||
|
|
||||||
Package `go-libvirt` provides a pure Go interface for interacting with libvirt.
|
Package `go-libvirt` provides a pure Go interface for interacting with libvirt.
|
||||||
|
|
||||||
Rather than using libvirt's C bindings, this package makes use of
|
Rather than using libvirt's C bindings, this package makes use of
|
||||||
libvirt's RPC interface, as documented [here](https://libvirt.org/internals/rpc.html).
|
libvirt's RPC interface, as documented [here](https://libvirt.org/kbase/internals/rpc.html).
|
||||||
Connections to the libvirt server may be local, or remote. RPC packets are encoded
|
Connections to the libvirt server may be local, or remote. RPC packets are encoded
|
||||||
using the XDR standard as defined by [RFC 4506](https://tools.ietf.org/html/rfc4506.html).
|
using the XDR standard as defined by [RFC 4506](https://tools.ietf.org/html/rfc4506.html).
|
||||||
|
|
||||||
@ -30,10 +33,15 @@ re-run the code generator. To do this, follow these steps:
|
|||||||
|
|
||||||
- First, download a copy of the libvirt sources corresponding to the version you
|
- First, download a copy of the libvirt sources corresponding to the version you
|
||||||
want to use.
|
want to use.
|
||||||
- Next, run `autogen.sh` in the libvirt directory. The autotools will check for
|
- Change directories into where you've unpacked your distribution of libvirt.
|
||||||
necessary libraries and prepare libvirt for building. We don't actually need
|
- The second step depends on the version of libvirt you'd like to build against.
|
||||||
to build libvirt, but we do require some header files that are produced in
|
It's not necessary to actually build libvirt, but it is necessary to run libvirt's
|
||||||
this step.
|
"configure" step because it generates required files.
|
||||||
|
- For libvirt < v6.7.0:
|
||||||
|
- `$ mkdir build; cd build`
|
||||||
|
- `$ ../autogen.sh`
|
||||||
|
- For libvirt >= v6.7.0:
|
||||||
|
- `$ meson setup build`
|
||||||
- Finally, set the environment variable `LIBVIRT_SOURCE` to the directory you
|
- Finally, set the environment variable `LIBVIRT_SOURCE` to the directory you
|
||||||
put libvirt into, and run `go generate ./...` from the go-libvirt directory.
|
put libvirt into, and run `go generate ./...` from the go-libvirt directory.
|
||||||
This runs both of the go-libvirt's code generators.
|
This runs both of the go-libvirt's code generators.
|
||||||
@ -169,3 +177,104 @@ ID Name UUID
|
|||||||
1 Test-1 dc329f87d4de47198cfd2e21c6105b01
|
1 Test-1 dc329f87d4de47198cfd2e21c6105b01
|
||||||
2 Test-2 dc229f87d4de47198cfd2e21c6105b01
|
2 Test-2 dc229f87d4de47198cfd2e21c6105b01
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Example (Connect to libvirt via TLS over TCP)
|
||||||
|
-------
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/digitalocean/go-libvirt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// This dials libvirt on the local machine
|
||||||
|
// It connects to libvirt via TLS over TCP
|
||||||
|
// To connect to a remote machine, you need to have the ca/cert/key of it.
|
||||||
|
keyFileXML, err := ioutil.ReadFile("/etc/pki/libvirt/private/clientkey.pem")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certFileXML, err := ioutil.ReadFile("/etc/pki/libvirt/clientcert.pem")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
caFileXML, err := ioutil.ReadFile("/etc/pki/CA/cacert.pem")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
cert, err := tls.X509KeyPair([]byte(certFileXML), []byte(keyFileXML))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
roots := x509.NewCertPool()
|
||||||
|
roots.AppendCertsFromPEM([]byte(caFileXML))
|
||||||
|
|
||||||
|
config := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
RootCAs: roots,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use host name or IP which is valid in certificate
|
||||||
|
addr := "10.10.10.10"
|
||||||
|
port := "16514"
|
||||||
|
c, err := tls.Dial("tcp", addr + ":" + port, config)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to dial libvirt: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop a byte before libvirt.New(c)
|
||||||
|
// More details at https://github.com/digitalocean/go-libvirt/issues/89
|
||||||
|
// Remove this line if the issue does not exist any more
|
||||||
|
c.Read(make([]byte, 1))
|
||||||
|
|
||||||
|
l := libvirt.New(c)
|
||||||
|
if err := l.Connect(); err != nil {
|
||||||
|
log.Fatalf("failed to connect: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := l.Version()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to retrieve libvirt version: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println("Version:", v)
|
||||||
|
|
||||||
|
// Return both running and stopped VMs
|
||||||
|
flags := libvirt.ConnectListDomainsActive | libvirt.ConnectListDomainsInactive
|
||||||
|
domains, _, err := l.ConnectListAllDomains(1, flags)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to retrieve domains: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("ID\tName\t\tUUID")
|
||||||
|
fmt.Println("--------------------------------------------------------")
|
||||||
|
for _, d := range domains {
|
||||||
|
fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := l.Disconnect(); err != nil {
|
||||||
|
log.Fatalf("failed to disconnect: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Running the Integration Tests
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Github actions workflows are defined in .github/worflows and can be triggered
|
||||||
|
manually in the github GUI after pushing a branch. There are not currently
|
||||||
|
convenient scripts for setting up and running integration tests locally, but
|
||||||
|
installing libvirt and defining only the artifacts described by the files in
|
||||||
|
testdata should be sufficient to be able to run the integration test file against.
|
||||||
|
|
||||||
|
1094
vendor/github.com/digitalocean/go-libvirt/const.gen.go
generated
vendored
1094
vendor/github.com/digitalocean/go-libvirt/const.gen.go
generated
vendored
File diff suppressed because it is too large
Load Diff
116
vendor/github.com/digitalocean/go-libvirt/doc.go
generated
vendored
116
vendor/github.com/digitalocean/go-libvirt/doc.go
generated
vendored
@ -12,65 +12,59 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
/*
|
// Package libvirt is a pure Go interface to libvirt.
|
||||||
Package libvirt provides a pure Go interface for Libvirt.
|
//
|
||||||
|
// Rather than using Libvirt's C bindings, this package makes use of Libvirt's
|
||||||
Rather than using Libvirt's C bindings, this package makes use of
|
// RPC interface, as documented here: https://libvirt.org/internals/rpc.html.
|
||||||
Libvirt's RPC interface, as documented here: https://libvirt.org/internals/rpc.html.
|
// Connections to the libvirt server may be local, or remote. RPC packets are
|
||||||
Connections to the libvirt server may be local, or remote. RPC packets are encoded
|
// encoded using the XDR standard as defined by RFC 4506.
|
||||||
using the XDR standard as defined by RFC 4506.
|
//
|
||||||
|
// Example usage:
|
||||||
This should be considered a work in progress. Most functionaly provided by the C
|
//
|
||||||
bindings have not yet made their way into this library. Pull requests are welcome!
|
// package main
|
||||||
The definition of the RPC protocol is in the libvirt source tree under src/rpc/virnetprotocol.x.
|
//
|
||||||
|
// import (
|
||||||
Example usage:
|
// "fmt"
|
||||||
|
// "log"
|
||||||
package main
|
// "net"
|
||||||
|
// "time"
|
||||||
import (
|
//
|
||||||
"fmt"
|
// "github.com/digitalocean/go-libvirt"
|
||||||
"log"
|
// )
|
||||||
"net"
|
//
|
||||||
"time"
|
// func main() {
|
||||||
|
// // This dials libvirt on the local machine, but you can substitute the first
|
||||||
"github.com/digitalocean/go-libvirt"
|
// // two parameters with "tcp", "<ip address>:<port>" to connect to libvirt on
|
||||||
)
|
// // a remote machine.
|
||||||
|
// c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", 2*time.Second)
|
||||||
func main() {
|
// if err != nil {
|
||||||
//c, err := net.DialTimeout("tcp", "127.0.0.1:16509", 2*time.Second)
|
// log.Fatalf("failed to dial libvirt: %v", err)
|
||||||
//c, err := net.DialTimeout("tcp", "192.168.1.12:16509", 2*time.Second)
|
// }
|
||||||
c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", 2*time.Second)
|
//
|
||||||
if err != nil {
|
// l := libvirt.New(c)
|
||||||
log.Fatalf("failed to dial libvirt: %v", err)
|
// if err := l.Connect(); err != nil {
|
||||||
}
|
// log.Fatalf("failed to connect: %v", err)
|
||||||
|
// }
|
||||||
l := libvirt.New(c)
|
//
|
||||||
if err := l.Connect(); err != nil {
|
// v, err := l.Version()
|
||||||
log.Fatalf("failed to connect: %v", err)
|
// if err != nil {
|
||||||
}
|
// log.Fatalf("failed to retrieve libvirt version: %v", err)
|
||||||
|
// }
|
||||||
v, err := l.Version()
|
// fmt.Println("Version:", v)
|
||||||
if err != nil {
|
//
|
||||||
log.Fatalf("failed to retrieve libvirt version: %v", err)
|
// domains, err := l.Domains()
|
||||||
}
|
// if err != nil {
|
||||||
fmt.Println("Version:", v)
|
// log.Fatalf("failed to retrieve domains: %v", err)
|
||||||
|
// }
|
||||||
domains, err := l.Domains()
|
//
|
||||||
if err != nil {
|
// fmt.Println("ID\tName\t\tUUID")
|
||||||
log.Fatalf("failed to retrieve domains: %v", err)
|
// fmt.Printf("--------------------------------------------------------\n")
|
||||||
}
|
// for _, d := range domains {
|
||||||
|
// fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
||||||
fmt.Println("ID\tName\t\tUUID")
|
// }
|
||||||
fmt.Printf("--------------------------------------------------------\n")
|
//
|
||||||
for _, d := range domains {
|
// if err := l.Disconnect(); err != nil {
|
||||||
fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
// log.Fatalf("failed to disconnect: %v", err)
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
if err := l.Disconnect(); err != nil {
|
|
||||||
log.Fatal("failed to disconnect: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
package libvirt
|
package libvirt
|
||||||
|
4
vendor/github.com/digitalocean/go-libvirt/internal/constants/remote_protocol.gen.go
generated
vendored
4
vendor/github.com/digitalocean/go-libvirt/internal/constants/remote_protocol.gen.go
generated
vendored
@ -881,6 +881,8 @@ const (
|
|||||||
ProcDomainAuthorizedSshKeysGet = 424
|
ProcDomainAuthorizedSshKeysGet = 424
|
||||||
// ProcDomainAuthorizedSshKeysSet is libvirt's REMOTE_PROC_DOMAIN_AUTHORIZED_SSH_KEYS_SET
|
// ProcDomainAuthorizedSshKeysSet is libvirt's REMOTE_PROC_DOMAIN_AUTHORIZED_SSH_KEYS_SET
|
||||||
ProcDomainAuthorizedSshKeysSet = 425
|
ProcDomainAuthorizedSshKeysSet = 425
|
||||||
|
// ProcDomainGetMessages is libvirt's REMOTE_PROC_DOMAIN_GET_MESSAGES
|
||||||
|
ProcDomainGetMessages = 426
|
||||||
|
|
||||||
|
|
||||||
// From consts:
|
// From consts:
|
||||||
@ -1010,6 +1012,8 @@ const (
|
|||||||
NetworkPortParametersMax = 16
|
NetworkPortParametersMax = 16
|
||||||
// DomainAuthorizedSshKeysMax is libvirt's REMOTE_DOMAIN_AUTHORIZED_SSH_KEYS_MAX
|
// DomainAuthorizedSshKeysMax is libvirt's REMOTE_DOMAIN_AUTHORIZED_SSH_KEYS_MAX
|
||||||
DomainAuthorizedSshKeysMax = 2048
|
DomainAuthorizedSshKeysMax = 2048
|
||||||
|
// DomainMessagesMax is libvirt's REMOTE_DOMAIN_MESSAGES_MAX
|
||||||
|
DomainMessagesMax = 2048
|
||||||
// DomainEventGraphicsIdentityMax is libvirt's REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX
|
// DomainEventGraphicsIdentityMax is libvirt's REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX
|
||||||
DomainEventGraphicsIdentityMax = 20
|
DomainEventGraphicsIdentityMax = 20
|
||||||
// Program is libvirt's REMOTE_PROGRAM
|
// Program is libvirt's REMOTE_PROGRAM
|
||||||
|
148
vendor/github.com/digitalocean/go-libvirt/internal/event/stream.go
generated
vendored
148
vendor/github.com/digitalocean/go-libvirt/internal/event/stream.go
generated
vendored
@ -14,7 +14,16 @@
|
|||||||
|
|
||||||
package event
|
package event
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// emptyEvent is used as a zero-value. Clients will never receive one of these;
|
||||||
|
// they are only here to satisfy the compiler. See the comments in process() for
|
||||||
|
// more information.
|
||||||
|
type emptyEvent struct{}
|
||||||
|
|
||||||
|
func (emptyEvent) GetCallbackID() int32 { return 0 }
|
||||||
|
|
||||||
// Stream is an unbounded buffered event channel. The implementation
|
// Stream is an unbounded buffered event channel. The implementation
|
||||||
// consists of a pair of unbuffered channels and a goroutine to manage them.
|
// consists of a pair of unbuffered channels and a goroutine to manage them.
|
||||||
@ -28,12 +37,45 @@ type Stream struct {
|
|||||||
|
|
||||||
// manage unbounded channel behavior.
|
// manage unbounded channel behavior.
|
||||||
queue []Event
|
queue []Event
|
||||||
|
qlen chan (chan int)
|
||||||
in, out chan Event
|
in, out chan Event
|
||||||
|
|
||||||
// terminates processing
|
// terminates processing
|
||||||
shutdown context.CancelFunc
|
shutdown context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewStream configures a new Event Stream. Incoming events are appended to a
|
||||||
|
// queue, which is then relayed to the listening client. Client behavior will
|
||||||
|
// not cause incoming events to block. It is the responsibility of the caller
|
||||||
|
// to terminate the Stream via Shutdown() when no longer in use.
|
||||||
|
func NewStream(program uint32, cbID int32) *Stream {
|
||||||
|
s := &Stream{
|
||||||
|
Program: program,
|
||||||
|
CallbackID: cbID,
|
||||||
|
in: make(chan Event),
|
||||||
|
out: make(chan Event),
|
||||||
|
qlen: make(chan (chan int)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the processing loop, which will return a routine we can use to
|
||||||
|
// shut the queue down later.
|
||||||
|
s.shutdown = s.start()
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len will return the current count of events in the internal queue for a
|
||||||
|
// stream. It does this by sending a message to the stream's process() loop,
|
||||||
|
// which will then write the current length to the channel contained in that
|
||||||
|
// message.
|
||||||
|
func (s *Stream) Len() int {
|
||||||
|
// Send a request to the process() loop to get the current length of the
|
||||||
|
// queue
|
||||||
|
ch := make(chan int)
|
||||||
|
s.qlen <- ch
|
||||||
|
return <-ch
|
||||||
|
}
|
||||||
|
|
||||||
// Recv returns the next available event from the Stream's queue.
|
// Recv returns the next available event from the Stream's queue.
|
||||||
func (s *Stream) Recv() chan Event {
|
func (s *Stream) Recv() chan Event {
|
||||||
return s.out
|
return s.out
|
||||||
@ -44,9 +86,9 @@ func (s *Stream) Push(e Event) {
|
|||||||
s.in <- e
|
s.in <- e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown gracefully terminates Stream processing, releasing all
|
// Shutdown gracefully terminates Stream processing, releasing all internal
|
||||||
// internal resources. Events which have not yet been received by the client
|
// resources. Events which have not yet been received by the client will be
|
||||||
// will be dropped. Subsequent calls to Shutdown() are idempotent.
|
// dropped. Subsequent calls to Shutdown() are idempotent.
|
||||||
func (s *Stream) Shutdown() {
|
func (s *Stream) Shutdown() {
|
||||||
if s.shutdown != nil {
|
if s.shutdown != nil {
|
||||||
s.shutdown()
|
s.shutdown()
|
||||||
@ -54,8 +96,7 @@ func (s *Stream) Shutdown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start starts the event processing loop, which will continue to run until
|
// start starts the event processing loop, which will continue to run until
|
||||||
// terminated by the returned context.CancelFunc. Starting a previously started
|
// terminated by the returned context.CancelFunc.
|
||||||
// Stream is an idempotent operation.
|
|
||||||
func (s *Stream) start() context.CancelFunc {
|
func (s *Stream) start() context.CancelFunc {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
@ -64,82 +105,53 @@ func (s *Stream) start() context.CancelFunc {
|
|||||||
return cancel
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
// process manages an Stream's lifecycle until canceled by the provided
|
// process manages an Stream's lifecycle until canceled by the provided context.
|
||||||
// context. Incoming events are appended to a queue which is then relayed to
|
// Incoming events are appended to a queue which is then relayed to the
|
||||||
// the a listening client. New events pushed onto the queue will not block due
|
// listening client. New events pushed onto the queue will not block if the
|
||||||
// to client behavior.
|
// client is not actively polling for them; the stream will buffer them
|
||||||
|
// internally.
|
||||||
func (s *Stream) process(ctx context.Context) {
|
func (s *Stream) process(ctx context.Context) {
|
||||||
defer func() {
|
// Close the output channel so that clients know this stream is finished.
|
||||||
close(s.in)
|
// We don't close s.in to avoid creating a race with the stream's Push()
|
||||||
close(s.out)
|
// function.
|
||||||
}()
|
defer close(s.out)
|
||||||
|
|
||||||
|
// This function is used to retrieve the next event from the queue, to be
|
||||||
|
// sent to the client. If there are no more events to send, it returns a nil
|
||||||
|
// channel and a zero-value event.
|
||||||
|
nextEvent := func() (chan Event, Event) {
|
||||||
|
sendCh := chan Event(nil)
|
||||||
|
next := Event(emptyEvent{})
|
||||||
|
if len(s.queue) > 0 {
|
||||||
|
sendCh = s.out
|
||||||
|
next = s.queue[0]
|
||||||
|
}
|
||||||
|
return sendCh, next
|
||||||
|
}
|
||||||
|
|
||||||
|
// The select statement in this loop relies on the fact that a send to a nil
|
||||||
|
// channel will block forever. If we have no entries in the queue, the
|
||||||
|
// sendCh variable will be nil, so the clause that attempts to send an event
|
||||||
|
// to the client will never complete. Clients will never receive an
|
||||||
|
// emptyEvent.
|
||||||
for {
|
for {
|
||||||
// informs send() to stop trying
|
sendCh, nextEvt := nextEvent()
|
||||||
nctx, next := context.WithCancel(ctx)
|
|
||||||
defer next()
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
// new event received, append to queue
|
// new event received, append to queue
|
||||||
case e := <-s.in:
|
case e := <-s.in:
|
||||||
s.queue = append(s.queue, e)
|
s.queue = append(s.queue, e)
|
||||||
|
|
||||||
// client recieved an event, pop from queue
|
case lenCh := <-s.qlen:
|
||||||
case <-s.send(nctx):
|
lenCh <- len(s.queue)
|
||||||
if len(s.queue) > 1 {
|
|
||||||
|
// client received an event, pop from queue
|
||||||
|
case sendCh <- nextEvt:
|
||||||
s.queue = s.queue[1:]
|
s.queue = s.queue[1:]
|
||||||
} else {
|
|
||||||
s.queue = []Event{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// shutdown requested
|
// shutdown requested
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
next()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send returns a channel which blocks until either the first item on the queue
|
|
||||||
// (if existing) is sent to the client, or the provided context is canceled.
|
|
||||||
// The stream's queue is never modified.
|
|
||||||
func (s *Stream) send(ctx context.Context) <-chan struct{} {
|
|
||||||
ch := make(chan struct{})
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer close(ch)
|
|
||||||
|
|
||||||
// do nothing and block if the queue is empty
|
|
||||||
if len(s.queue) == 0 {
|
|
||||||
<-ctx.Done()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise, attempt to send the event
|
|
||||||
select {
|
|
||||||
case s.out <- s.queue[0]:
|
|
||||||
case <-ctx.Done():
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewStream configures a new Event Stream. Incoming events are appended to a
|
|
||||||
// queue, which is then relayed to the listening client. Client behavior will
|
|
||||||
// not cause incoming events to block. It is the responsibility of the caller
|
|
||||||
// to terminate the Stream via Shutdown() when no longer in use.
|
|
||||||
func NewStream(program uint32, cbID int32) *Stream {
|
|
||||||
ic := &Stream{
|
|
||||||
Program: program,
|
|
||||||
CallbackID: cbID,
|
|
||||||
in: make(chan Event),
|
|
||||||
out: make(chan Event),
|
|
||||||
}
|
|
||||||
|
|
||||||
ic.shutdown = ic.start()
|
|
||||||
|
|
||||||
return ic
|
|
||||||
}
|
}
|
||||||
|
237
vendor/github.com/digitalocean/go-libvirt/libvirt.go
generated
vendored
237
vendor/github.com/digitalocean/go-libvirt/libvirt.go
generated
vendored
@ -12,8 +12,6 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// Package libvirt is a pure Go implementation of the libvirt RPC protocol.
|
|
||||||
// For more information on the protocol, see https://libvirt.org/internals/l.html
|
|
||||||
package libvirt
|
package libvirt
|
||||||
|
|
||||||
// We'll use c-for-go to extract the consts and typedefs from the libvirt
|
// We'll use c-for-go to extract the consts and typedefs from the libvirt
|
||||||
@ -21,7 +19,6 @@ package libvirt
|
|||||||
//go:generate scripts/gen-consts.sh
|
//go:generate scripts/gen-consts.sh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -29,22 +26,47 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||||
"github.com/digitalocean/go-libvirt/internal/event"
|
"github.com/digitalocean/go-libvirt/internal/event"
|
||||||
xdr "github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2"
|
xdr "github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2"
|
||||||
|
"github.com/digitalocean/go-libvirt/socket"
|
||||||
|
"github.com/digitalocean/go-libvirt/socket/dialers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrEventsNotSupported is returned by Events() if event streams
|
// ErrEventsNotSupported is returned by Events() if event streams
|
||||||
// are unsupported by either QEMU or libvirt.
|
// are unsupported by either QEMU or libvirt.
|
||||||
var ErrEventsNotSupported = errors.New("event monitor is not supported")
|
var ErrEventsNotSupported = errors.New("event monitor is not supported")
|
||||||
|
|
||||||
|
// ConnectURI defines a type for driver URIs for libvirt
|
||||||
|
// the defined constants are *not* exhaustive as there are also options
|
||||||
|
// e.g. to connect remote via SSH
|
||||||
|
type ConnectURI string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// QEMUSystem connects to a QEMU system mode daemon
|
||||||
|
QEMUSystem ConnectURI = "qemu:///system"
|
||||||
|
// QEMUSession connects to a QEMU session mode daemon (unprivileged)
|
||||||
|
QEMUSession ConnectURI = "qemu:///session"
|
||||||
|
// XenSystem connects to a Xen system mode daemon
|
||||||
|
XenSystem ConnectURI = "xen:///system"
|
||||||
|
//TestDefault connect to default mock driver
|
||||||
|
TestDefault ConnectURI = "test:///default"
|
||||||
|
|
||||||
|
// disconnectedTimeout is how long to wait for disconnect cleanup to
|
||||||
|
// complete
|
||||||
|
disconnectTimeout = 5 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
// Libvirt implements libvirt's remote procedure call protocol.
|
// Libvirt implements libvirt's remote procedure call protocol.
|
||||||
type Libvirt struct {
|
type Libvirt struct {
|
||||||
conn net.Conn
|
// socket connection
|
||||||
r *bufio.Reader
|
socket *socket.Socket
|
||||||
w *bufio.Writer
|
// closed after cleanup complete following the underlying connection to
|
||||||
mu *sync.Mutex
|
// libvirt being disconnected.
|
||||||
|
disconnected chan struct{}
|
||||||
|
|
||||||
// method callbacks
|
// method callbacks
|
||||||
cmux sync.RWMutex
|
cmux sync.RWMutex
|
||||||
@ -93,16 +115,39 @@ func (l *Libvirt) Capabilities() ([]byte, error) {
|
|||||||
return []byte(caps), err
|
return []byte(caps), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect establishes communication with the libvirt server.
|
// called at connection time, authenticating with all supported auth types
|
||||||
// The underlying libvirt socket connection must be previously established.
|
func (l *Libvirt) authenticate() error {
|
||||||
func (l *Libvirt) Connect() error {
|
// libvirt requires that we call auth-list prior to connecting,
|
||||||
|
// even when no authentication is used.
|
||||||
|
resp, err := l.AuthList()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, auth := range resp {
|
||||||
|
switch auth {
|
||||||
|
case constants.AuthNone:
|
||||||
|
case constants.AuthPolkit:
|
||||||
|
_, err := l.AuthPolkit()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Libvirt) initLibvirtComms(uri ConnectURI) error {
|
||||||
payload := struct {
|
payload := struct {
|
||||||
Padding [3]byte
|
Padding [3]byte
|
||||||
Name string
|
Name string
|
||||||
Flags uint32
|
Flags uint32
|
||||||
}{
|
}{
|
||||||
Padding: [3]byte{0x1, 0x0, 0x0},
|
Padding: [3]byte{0x1, 0x0, 0x0},
|
||||||
Name: "qemu:///system",
|
Name: string(uri),
|
||||||
Flags: 0,
|
Flags: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,9 +156,7 @@ func (l *Libvirt) Connect() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// libvirt requires that we call auth-list prior to connecting,
|
err = l.authenticate()
|
||||||
// event when no authentication is used.
|
|
||||||
_, err = l.request(constants.ProcAuthList, constants.Program, buf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -126,24 +169,76 @@ func (l *Libvirt) Connect() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect shuts down communication with the libvirt server and closes the
|
// ConnectToURI establishes communication with the specified libvirt driver
|
||||||
// underlying net.Conn.
|
// The underlying libvirt socket connection will be created via the dialer.
|
||||||
func (l *Libvirt) Disconnect() error {
|
// Since the connection can be lost, the Disconnected function can be used
|
||||||
// close event streams
|
// to monitor for a lost connection.
|
||||||
for _, ev := range l.events {
|
func (l *Libvirt) ConnectToURI(uri ConnectURI) error {
|
||||||
l.unsubscribeEvents(ev)
|
err := l.socket.Connect()
|
||||||
}
|
|
||||||
|
|
||||||
// Deregister all callbacks to prevent blocking on clients with
|
|
||||||
// outstanding requests
|
|
||||||
l.deregisterAll()
|
|
||||||
|
|
||||||
_, err := l.request(constants.ProcConnectClose, constants.Program, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return l.conn.Close()
|
// Start watching the underlying socket connection immediately.
|
||||||
|
// If we don't, and Libvirt goes away partway through initLibvirtComms,
|
||||||
|
// then the callbacks that initLibvirtComms has registered will never
|
||||||
|
// be closed, and therefore it will be stuck waiting for data from a
|
||||||
|
// channel that will never arrive.
|
||||||
|
go l.waitAndDisconnect()
|
||||||
|
|
||||||
|
err = l.initLibvirtComms(uri)
|
||||||
|
if err != nil {
|
||||||
|
l.socket.Disconnect()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
l.disconnected = make(chan struct{})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect establishes communication with the libvirt server.
|
||||||
|
// The underlying libvirt socket connection will be created via the dialer.
|
||||||
|
// Since the connection can be lost, the Disconnected function can be used
|
||||||
|
// to monitor for a lost connection.
|
||||||
|
func (l *Libvirt) Connect() error {
|
||||||
|
return l.ConnectToURI(QEMUSystem)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnect shuts down communication with the libvirt server and closes the
|
||||||
|
// underlying net.Conn.
|
||||||
|
func (l *Libvirt) Disconnect() error {
|
||||||
|
// Ordering is important here. We want to make sure the connection is closed
|
||||||
|
// before unsubscribing and deregistering the events and requests, to
|
||||||
|
// prevent new requests from racing.
|
||||||
|
_, err := l.request(constants.ProcConnectClose, constants.Program, nil)
|
||||||
|
|
||||||
|
// syscall.EINVAL is returned by the socket pkg when things have already
|
||||||
|
// been disconnected.
|
||||||
|
if err != nil && err != syscall.EINVAL {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = l.socket.Disconnect()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for the listen goroutine to detect the lost connection and clean up
|
||||||
|
// to happen once it returns. Safeguard with a timeout.
|
||||||
|
// Things not fully cleaned up is better than a deadlock.
|
||||||
|
select {
|
||||||
|
case <-l.disconnected:
|
||||||
|
case <-time.After(disconnectTimeout):
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnected allows callers to detect if the underlying connection
|
||||||
|
// to libvirt has been closed. If the returned channel is closed, then
|
||||||
|
// the connection to libvirt has been lost (or disconnected intentionally).
|
||||||
|
func (l *Libvirt) Disconnected() <-chan struct{} {
|
||||||
|
return l.disconnected
|
||||||
}
|
}
|
||||||
|
|
||||||
// Domains returns a list of all domains managed by libvirt.
|
// Domains returns a list of all domains managed by libvirt.
|
||||||
@ -192,7 +287,7 @@ func (l *Libvirt) SubscribeQEMUEvents(ctx context.Context, dom string) (<-chan D
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
defer l.unsubscribeQEMUEvents(stream)
|
defer l.unsubscribeQEMUEvents(stream)
|
||||||
defer stream.Shutdown()
|
defer stream.Shutdown()
|
||||||
defer func() { close(ch) }()
|
defer close(ch)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -260,10 +355,10 @@ func (l *Libvirt) SubscribeEvents(ctx context.Context, eventID DomainEventID,
|
|||||||
|
|
||||||
// unsubscribeEvents stops the flow of the specified events from libvirt. There
|
// unsubscribeEvents stops the flow of the specified events from libvirt. There
|
||||||
// are two steps to this process: a call to libvirt to deregister our callback,
|
// are two steps to this process: a call to libvirt to deregister our callback,
|
||||||
// and then removing the callback from the list used by the `route` fucntion. If
|
// and then removing the callback from the list used by the `Route` function. If
|
||||||
// the deregister call fails, we'll return the error, but still remove the
|
// the deregister call fails, we'll return the error, but still remove the
|
||||||
// callback from the list. That's ok; if any events arrive after this point, the
|
// callback from the list. That's ok; if any events arrive after this point, the
|
||||||
// route function will drop them when it finds no registered handler.
|
// Route function will drop them when it finds no registered handler.
|
||||||
func (l *Libvirt) unsubscribeEvents(stream *event.Stream) error {
|
func (l *Libvirt) unsubscribeEvents(stream *event.Stream) error {
|
||||||
err := l.ConnectDomainEventCallbackDeregisterAny(stream.CallbackID)
|
err := l.ConnectDomainEventCallbackDeregisterAny(stream.CallbackID)
|
||||||
l.removeStream(stream.CallbackID)
|
l.removeStream(stream.CallbackID)
|
||||||
@ -590,19 +685,85 @@ func getQEMUError(r response) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// New configures a new Libvirt RPC connection.
|
func (l *Libvirt) waitAndDisconnect() {
|
||||||
func New(conn net.Conn) *Libvirt {
|
// wait for the socket to indicate if/when it's been disconnected
|
||||||
|
<-l.socket.Disconnected()
|
||||||
|
|
||||||
|
// close event streams
|
||||||
|
l.removeAllStreams()
|
||||||
|
|
||||||
|
// Deregister all callbacks to prevent blocking on clients with
|
||||||
|
// outstanding requests
|
||||||
|
l.deregisterAll()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-l.disconnected:
|
||||||
|
// l.disconnected is already closed, i.e., Libvirt.ConnectToURI
|
||||||
|
// was unable to complete all phases of its connection and
|
||||||
|
// so this hadn't been assigned to an open channel yet (it
|
||||||
|
// is set to a closed channel in Libvirt.New*)
|
||||||
|
//
|
||||||
|
// Just return to avoid closing an already-closed channel.
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
// if we make it here then reading from l.disconnected is blocking,
|
||||||
|
// which suggests that it is open and must be closed.
|
||||||
|
}
|
||||||
|
|
||||||
|
close(l.disconnected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithDialer configures a new Libvirt object that can be used to perform
|
||||||
|
// RPCs via libvirt's socket. The actual connection will not be established
|
||||||
|
// until Connect is called. The same Libvirt object may be used to re-connect
|
||||||
|
// multiple times.
|
||||||
|
func NewWithDialer(dialer socket.Dialer) *Libvirt {
|
||||||
l := &Libvirt{
|
l := &Libvirt{
|
||||||
conn: conn,
|
|
||||||
s: 0,
|
s: 0,
|
||||||
r: bufio.NewReader(conn),
|
disconnected: make(chan struct{}),
|
||||||
w: bufio.NewWriter(conn),
|
|
||||||
mu: &sync.Mutex{},
|
|
||||||
callbacks: make(map[int32]chan response),
|
callbacks: make(map[int32]chan response),
|
||||||
events: make(map[int32]*event.Stream),
|
events: make(map[int32]*event.Stream),
|
||||||
}
|
}
|
||||||
|
|
||||||
go l.listen()
|
l.socket = socket.New(dialer, l)
|
||||||
|
|
||||||
|
// we start with a closed channel since that indicates no connection
|
||||||
|
close(l.disconnected)
|
||||||
|
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New configures a new Libvirt RPC connection.
|
||||||
|
// This function only remains to retain backwards compatability.
|
||||||
|
// When Libvirt's Connect function is called, the Dial will simply return the
|
||||||
|
// connection passed in here and start a goroutine listening/reading from it.
|
||||||
|
// If at any point the Disconnect function is called, any subsequent Connect
|
||||||
|
// call will simply return an already closed connection.
|
||||||
|
//
|
||||||
|
// Deprecated: Please use NewWithDialer.
|
||||||
|
func New(conn net.Conn) *Libvirt {
|
||||||
|
return NewWithDialer(dialers.NewAlreadyConnected(conn))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkUpdateCompat is a wrapper over NetworkUpdate which swaps `Command` and `Section` when needed.
|
||||||
|
// This function must be used instead of NetworkUpdate to be sure that the
|
||||||
|
// NetworkUpdate call works both with older and newer libvirtd connections.
|
||||||
|
//
|
||||||
|
// libvirt on-wire protocol had a bug for a long time where Command and Section
|
||||||
|
// were reversed. It's been fixed in newer libvirt versions, and backported to
|
||||||
|
// some older versions. This helper detects what argument order libvirtd expects
|
||||||
|
// and makes the correct NetworkUpdate call.
|
||||||
|
func (l *Libvirt) NetworkUpdateCompat(Net Network, Command NetworkUpdateCommand, Section NetworkUpdateSection, ParentIndex int32, XML string, Flags NetworkUpdateFlags) (err error) {
|
||||||
|
// This is defined in libvirt/src/libvirt_internal.h and thus not available in go-libvirt autogenerated code
|
||||||
|
const virDrvFeatureNetworkUpdateHasCorrectOrder = 16
|
||||||
|
hasCorrectOrder, err := l.ConnectSupportsFeature(virDrvFeatureNetworkUpdateHasCorrectOrder)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to confirm argument order for NetworkUpdate: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://gitlab.com/libvirt/libvirt/-/commit/b0f78d626a18bcecae3a4d165540ab88bfbfc9ee
|
||||||
|
if hasCorrectOrder == 0 {
|
||||||
|
return l.NetworkUpdate(Net, uint32(Section), uint32(Command), ParentIndex, XML, Flags)
|
||||||
|
}
|
||||||
|
return l.NetworkUpdate(Net, uint32(Command), uint32(Section), ParentIndex, XML, Flags)
|
||||||
|
}
|
||||||
|
4
vendor/github.com/digitalocean/go-libvirt/libvirt.yml
generated
vendored
4
vendor/github.com/digitalocean/go-libvirt/libvirt.yml
generated
vendored
@ -27,7 +27,7 @@ PARSER:
|
|||||||
# rely on our caller to link the libvirt source directory to lv_source/, and
|
# rely on our caller to link the libvirt source directory to lv_source/, and
|
||||||
# run on that code. This isn't ideal, but changes to c-for-go are needed to
|
# run on that code. This isn't ideal, but changes to c-for-go are needed to
|
||||||
# fix it.
|
# fix it.
|
||||||
IncludePaths: [./lv_source/include]
|
IncludePaths: [./lv_source/include, ./lv_source/build/include]
|
||||||
SourcesPaths:
|
SourcesPaths:
|
||||||
- libvirt/libvirt.h
|
- libvirt/libvirt.h
|
||||||
- libvirt/virterror.h
|
- libvirt/virterror.h
|
||||||
@ -56,7 +56,7 @@ TRANSLATOR:
|
|||||||
- {action: replace, from: "Rpc([A-Z]|$)", to: "RPC$1"}
|
- {action: replace, from: "Rpc([A-Z]|$)", to: "RPC$1"}
|
||||||
- {action: replace, from: "Ssh([A-Z]|$)", to: "SSH$1"}
|
- {action: replace, from: "Ssh([A-Z]|$)", to: "SSH$1"}
|
||||||
- {action: replace, from: "Http([A-Z]|$)", to: "HTTP$1"}
|
- {action: replace, from: "Http([A-Z]|$)", to: "HTTP$1"}
|
||||||
- {transform: unexport, from: "^(Err|From|War)"}
|
- {transform: unexport, from: "^From"}
|
||||||
const:
|
const:
|
||||||
- {action: accept, from: "^VIR_"}
|
- {action: accept, from: "^VIR_"}
|
||||||
# Special case to prevent a collision with a type:
|
# Special case to prevent a collision with a type:
|
||||||
|
7
vendor/github.com/digitalocean/go-libvirt/libvirtd.conf
generated
vendored
7
vendor/github.com/digitalocean/go-libvirt/libvirtd.conf
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
# libvirtd configuration for travis-ci
|
|
||||||
listen_tls = 0
|
|
||||||
listen_tcp = 1
|
|
||||||
tcp_port = "16509"
|
|
||||||
listen_addr = "127.0.0.1"
|
|
||||||
auth_unix_rw = "none"
|
|
||||||
auth_tcp = "none"
|
|
55
vendor/github.com/digitalocean/go-libvirt/remote_protocol.gen.go
generated
vendored
55
vendor/github.com/digitalocean/go-libvirt/remote_protocol.gen.go
generated
vendored
@ -147,8 +147,8 @@ type DomainSnapshot struct {
|
|||||||
Dom Domain
|
Dom Domain
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error is libvirt's remote_error
|
// remote_error is libvirt's remote_error
|
||||||
type Error struct {
|
type remote_error struct {
|
||||||
Code int32
|
Code int32
|
||||||
OptDomain int32
|
OptDomain int32
|
||||||
Message OptString
|
Message OptString
|
||||||
@ -191,7 +191,7 @@ type NodeGetMemoryStats struct {
|
|||||||
// DomainDiskError is libvirt's remote_domain_disk_error
|
// DomainDiskError is libvirt's remote_domain_disk_error
|
||||||
type DomainDiskError struct {
|
type DomainDiskError struct {
|
||||||
Disk string
|
Disk string
|
||||||
Error int32
|
remote_error int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectOpenArgs is libvirt's remote_connect_open_args
|
// ConnectOpenArgs is libvirt's remote_connect_open_args
|
||||||
@ -1371,7 +1371,7 @@ type DomainGetCPUStatsRet struct {
|
|||||||
// DomainGetHostnameArgs is libvirt's remote_domain_get_hostname_args
|
// DomainGetHostnameArgs is libvirt's remote_domain_get_hostname_args
|
||||||
type DomainGetHostnameArgs struct {
|
type DomainGetHostnameArgs struct {
|
||||||
Dom Domain
|
Dom Domain
|
||||||
Flags uint32
|
Flags DomainGetHostnameFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
// DomainGetHostnameRet is libvirt's remote_domain_get_hostname_ret
|
// DomainGetHostnameRet is libvirt's remote_domain_get_hostname_ret
|
||||||
@ -4119,6 +4119,17 @@ type DomainAuthorizedSshKeysSetArgs struct {
|
|||||||
Flags uint32
|
Flags uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DomainGetMessagesArgs is libvirt's remote_domain_get_messages_args
|
||||||
|
type DomainGetMessagesArgs struct {
|
||||||
|
Dom Domain
|
||||||
|
Flags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainGetMessagesRet is libvirt's remote_domain_get_messages_ret
|
||||||
|
type DomainGetMessagesRet struct {
|
||||||
|
Msgs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TypedParamValue is a discriminated union.
|
// TypedParamValue is a discriminated union.
|
||||||
type TypedParamValue struct {
|
type TypedParamValue struct {
|
||||||
@ -12387,7 +12398,7 @@ func (l *Libvirt) DomainEventBalloonChange() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DomainGetHostname is the go wrapper for REMOTE_PROC_DOMAIN_GET_HOSTNAME.
|
// DomainGetHostname is the go wrapper for REMOTE_PROC_DOMAIN_GET_HOSTNAME.
|
||||||
func (l *Libvirt) DomainGetHostname(Dom Domain, Flags uint32) (rHostname string, err error) {
|
func (l *Libvirt) DomainGetHostname(Dom Domain, Flags DomainGetHostnameFlags) (rHostname string, err error) {
|
||||||
var buf []byte
|
var buf []byte
|
||||||
|
|
||||||
args := DomainGetHostnameArgs {
|
args := DomainGetHostnameArgs {
|
||||||
@ -16447,3 +16458,37 @@ func (l *Libvirt) DomainAuthorizedSshKeysSet(Dom Domain, User string, Keys []str
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DomainGetMessages is the go wrapper for REMOTE_PROC_DOMAIN_GET_MESSAGES.
|
||||||
|
func (l *Libvirt) DomainGetMessages(Dom Domain, Flags uint32) (rMsgs []string, err error) {
|
||||||
|
var buf []byte
|
||||||
|
|
||||||
|
args := DomainGetMessagesArgs {
|
||||||
|
Dom: Dom,
|
||||||
|
Flags: Flags,
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err = encode(&args)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var r response
|
||||||
|
r, err = l.requestStream(426, constants.Program, buf, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return value unmarshaling
|
||||||
|
tpd := typedParamDecoder{}
|
||||||
|
ct := map[string]xdr.TypeDecoder{"libvirt.TypedParam": tpd}
|
||||||
|
rdr := bytes.NewReader(r.Payload)
|
||||||
|
dec := xdr.NewDecoderCustomTypes(rdr, 0, ct)
|
||||||
|
// Msgs: []string
|
||||||
|
_, err = dec.Decode(&rMsgs)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
287
vendor/github.com/digitalocean/go-libvirt/rpc.go
generated
vendored
287
vendor/github.com/digitalocean/go-libvirt/rpc.go
generated
vendored
@ -16,166 +16,55 @@ package libvirt
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||||
"github.com/digitalocean/go-libvirt/internal/event"
|
"github.com/digitalocean/go-libvirt/internal/event"
|
||||||
xdr "github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2"
|
xdr "github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2"
|
||||||
|
"github.com/digitalocean/go-libvirt/socket"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrUnsupported is returned if a procedure is not supported by libvirt
|
// ErrUnsupported is returned if a procedure is not supported by libvirt
|
||||||
var ErrUnsupported = errors.New("unsupported procedure requested")
|
var ErrUnsupported = errors.New("unsupported procedure requested")
|
||||||
|
|
||||||
// request and response types
|
|
||||||
const (
|
|
||||||
// Call is used when making calls to the remote server.
|
|
||||||
Call = iota
|
|
||||||
|
|
||||||
// Reply indicates a server reply.
|
|
||||||
Reply
|
|
||||||
|
|
||||||
// Message is an asynchronous notification.
|
|
||||||
Message
|
|
||||||
|
|
||||||
// Stream represents a stream data packet.
|
|
||||||
Stream
|
|
||||||
|
|
||||||
// CallWithFDs is used by a client to indicate the request has
|
|
||||||
// arguments with file descriptors.
|
|
||||||
CallWithFDs
|
|
||||||
|
|
||||||
// ReplyWithFDs is used by a server to indicate the request has
|
|
||||||
// arguments with file descriptors.
|
|
||||||
ReplyWithFDs
|
|
||||||
)
|
|
||||||
|
|
||||||
// request and response statuses
|
|
||||||
const (
|
|
||||||
// StatusOK is always set for method calls or events.
|
|
||||||
// For replies it indicates successful completion of the method.
|
|
||||||
// For streams it indicates confirmation of the end of file on the stream.
|
|
||||||
StatusOK = iota
|
|
||||||
|
|
||||||
// StatusError for replies indicates that the method call failed
|
|
||||||
// and error information is being returned. For streams this indicates
|
|
||||||
// that not all data was sent and the stream has aborted.
|
|
||||||
StatusError
|
|
||||||
|
|
||||||
// StatusContinue is only used for streams.
|
|
||||||
// This indicates that further data packets will be following.
|
|
||||||
StatusContinue
|
|
||||||
)
|
|
||||||
|
|
||||||
// header is a libvirt rpc packet header
|
|
||||||
type header struct {
|
|
||||||
// Program identifier
|
|
||||||
Program uint32
|
|
||||||
|
|
||||||
// Program version
|
|
||||||
Version uint32
|
|
||||||
|
|
||||||
// Remote procedure identifier
|
|
||||||
Procedure uint32
|
|
||||||
|
|
||||||
// Call type, e.g., Reply
|
|
||||||
Type uint32
|
|
||||||
|
|
||||||
// Call serial number
|
|
||||||
Serial int32
|
|
||||||
|
|
||||||
// Request status, e.g., StatusOK
|
|
||||||
Status uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// packet represents a RPC request or response.
|
|
||||||
type packet struct {
|
|
||||||
// Size of packet, in bytes, including length.
|
|
||||||
// Len + Header + Payload
|
|
||||||
Len uint32
|
|
||||||
Header header
|
|
||||||
}
|
|
||||||
|
|
||||||
// Global packet instance, for use with unsafe.Sizeof()
|
|
||||||
var _p packet
|
|
||||||
|
|
||||||
// internal rpc response
|
// internal rpc response
|
||||||
type response struct {
|
type response struct {
|
||||||
Payload []byte
|
Payload []byte
|
||||||
Status uint32
|
Status uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// libvirt error response
|
// Error reponse from libvirt
|
||||||
type libvirtError struct {
|
type Error struct {
|
||||||
Code uint32
|
Code uint32
|
||||||
DomainID uint32
|
|
||||||
Padding uint8
|
|
||||||
Message string
|
Message string
|
||||||
Level uint32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e libvirtError) Error() string {
|
func (e Error) Error() string {
|
||||||
return e.Message
|
return e.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkError is used to check whether an error is a libvirtError, and if it is,
|
// checkError is used to check whether an error is a libvirtError, and if it is,
|
||||||
// whether its error code matches the one passed in. It will return false if
|
// whether its error code matches the one passed in. It will return false if
|
||||||
// these conditions are not met.
|
// these conditions are not met.
|
||||||
func checkError(err error, expectedError errorNumber) bool {
|
func checkError(err error, expectedError ErrorNumber) bool {
|
||||||
e, ok := err.(libvirtError)
|
for err != nil {
|
||||||
|
e, ok := err.(Error)
|
||||||
if ok {
|
if ok {
|
||||||
return e.Code == uint32(expectedError)
|
return e.Code == uint32(expectedError)
|
||||||
}
|
}
|
||||||
|
err = errors.Unwrap(err)
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotFound detects libvirt's ERR_NO_DOMAIN.
|
// IsNotFound detects libvirt's ERR_NO_DOMAIN.
|
||||||
func IsNotFound(err error) bool {
|
func IsNotFound(err error) bool {
|
||||||
return checkError(err, errNoDomain)
|
return checkError(err, ErrNoDomain)
|
||||||
}
|
|
||||||
|
|
||||||
// listen processes incoming data and routes
|
|
||||||
// responses to their respective callback handler.
|
|
||||||
func (l *Libvirt) listen() {
|
|
||||||
for {
|
|
||||||
// response packet length
|
|
||||||
length, err := pktlen(l.r)
|
|
||||||
if err != nil {
|
|
||||||
// When the underlying connection EOFs or is closed, stop
|
|
||||||
// this goroutine
|
|
||||||
if err == io.EOF || strings.Contains(err.Error(), "use of closed network connection") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalid packet
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// response header
|
|
||||||
h, err := extractHeader(l.r)
|
|
||||||
if err != nil {
|
|
||||||
// invalid packet
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// payload: packet length minus what was previously read
|
|
||||||
size := int(length) - int(unsafe.Sizeof(_p))
|
|
||||||
buf := make([]byte, size)
|
|
||||||
_, err = io.ReadFull(l.r, buf)
|
|
||||||
if err != nil {
|
|
||||||
// invalid packet
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// route response to caller
|
|
||||||
l.route(h, buf)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// callback sends RPC responses to respective callers.
|
// callback sends RPC responses to respective callers.
|
||||||
@ -191,9 +80,9 @@ func (l *Libvirt) callback(id int32, res response) {
|
|||||||
c <- res
|
c <- res
|
||||||
}
|
}
|
||||||
|
|
||||||
// route sends incoming packets to their listeners.
|
// Route sends incoming packets to their listeners.
|
||||||
func (l *Libvirt) route(h *header, buf []byte) {
|
func (l *Libvirt) Route(h *socket.Header, buf []byte) {
|
||||||
// route events to their respective listener
|
// Route events to their respective listener
|
||||||
var event event.Event
|
var event event.Event
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@ -243,24 +132,36 @@ func (l *Libvirt) addStream(s *event.Stream) {
|
|||||||
l.events[s.CallbackID] = s
|
l.events[s.CallbackID] = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeStream notifies the libvirt server to stop sending events for the
|
// removeStream deletes an event stream. The caller should first notify libvirt
|
||||||
// provided callback ID. Upon successful de-registration the callback handler
|
// to stop sending events for this stream. Subsequent calls to removeStream are
|
||||||
// is destroyed. Subsequent calls to removeStream are idempotent and return
|
// idempotent and return nil.
|
||||||
// nil.
|
|
||||||
// TODO: Fix this comment
|
|
||||||
func (l *Libvirt) removeStream(id int32) error {
|
func (l *Libvirt) removeStream(id int32) error {
|
||||||
l.emux.Lock()
|
l.emux.Lock()
|
||||||
defer l.emux.Unlock()
|
defer l.emux.Unlock()
|
||||||
|
|
||||||
// if the event is already removed, just return nil
|
// if the event is already removed, just return nil
|
||||||
_, ok := l.events[id]
|
q, ok := l.events[id]
|
||||||
if ok {
|
if ok {
|
||||||
delete(l.events, id)
|
delete(l.events, id)
|
||||||
|
q.Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removeAllStreams deletes all event streams. This is meant to be used to
|
||||||
|
// clean up only once the underlying connection to libvirt is disconnected and
|
||||||
|
// thus does not attempt to notify libvirt to stop sending events.
|
||||||
|
func (l *Libvirt) removeAllStreams() {
|
||||||
|
l.emux.Lock()
|
||||||
|
defer l.emux.Unlock()
|
||||||
|
|
||||||
|
for _, ev := range l.events {
|
||||||
|
ev.Shutdown()
|
||||||
|
delete(l.events, ev.CallbackID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// register configures a method response callback
|
// register configures a method response callback
|
||||||
func (l *Libvirt) register(id int32, c chan response) {
|
func (l *Libvirt) register(id int32, c chan response) {
|
||||||
l.cmux.Lock()
|
l.cmux.Lock()
|
||||||
@ -316,7 +217,8 @@ func (l *Libvirt) requestStream(proc uint32, program uint32, payload []byte,
|
|||||||
l.deregister(serial)
|
l.deregister(serial)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err := l.sendPacket(serial, proc, program, payload, Call, StatusOK)
|
err := l.socket.SendPacket(serial, proc, program, payload, socket.Call,
|
||||||
|
socket.StatusOK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response{}, err
|
return response{}, err
|
||||||
}
|
}
|
||||||
@ -330,7 +232,7 @@ func (l *Libvirt) requestStream(proc uint32, program uint32, payload []byte,
|
|||||||
abort := make(chan bool)
|
abort := make(chan bool)
|
||||||
outErr := make(chan error)
|
outErr := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
outErr <- l.sendStream(serial, proc, program, out, abort)
|
outErr <- l.socket.SendStream(serial, proc, program, out, abort)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Even without incoming stream server sends confirmation once all data is received
|
// Even without incoming stream server sends confirmation once all data is received
|
||||||
@ -365,7 +267,7 @@ func (l *Libvirt) processIncomingStream(c chan response, inStream io.Writer) (re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StatusOK indicates end of stream
|
// StatusOK indicates end of stream
|
||||||
if resp.Status == StatusOK {
|
if resp.Status == socket.StatusOK {
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,77 +288,9 @@ func (l *Libvirt) processIncomingStream(c chan response, inStream io.Writer) (re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Libvirt) sendStream(serial int32, proc uint32, program uint32, stream io.Reader, abort chan bool) error {
|
|
||||||
// Keep total packet length under 4 MiB to follow possible limitation in libvirt server code
|
|
||||||
buf := make([]byte, 4*MiB-unsafe.Sizeof(_p))
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-abort:
|
|
||||||
return l.sendPacket(serial, proc, program, nil, Stream, StatusError)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
n, err := stream.Read(buf)
|
|
||||||
if n > 0 {
|
|
||||||
err2 := l.sendPacket(serial, proc, program, buf[:n], Stream, StatusContinue)
|
|
||||||
if err2 != nil {
|
|
||||||
return err2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if err == io.EOF {
|
|
||||||
return l.sendPacket(serial, proc, program, nil, Stream, StatusOK)
|
|
||||||
}
|
|
||||||
// keep original error
|
|
||||||
err2 := l.sendPacket(serial, proc, program, nil, Stream, StatusError)
|
|
||||||
if err2 != nil {
|
|
||||||
return err2
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Libvirt) sendPacket(serial int32, proc uint32, program uint32, payload []byte, typ uint32, status uint32) error {
|
|
||||||
|
|
||||||
p := packet{
|
|
||||||
Header: header{
|
|
||||||
Program: program,
|
|
||||||
Version: constants.ProtocolVersion,
|
|
||||||
Procedure: proc,
|
|
||||||
Type: typ,
|
|
||||||
Serial: serial,
|
|
||||||
Status: status,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
size := int(unsafe.Sizeof(p.Len)) + int(unsafe.Sizeof(p.Header))
|
|
||||||
if payload != nil {
|
|
||||||
size += len(payload)
|
|
||||||
}
|
|
||||||
p.Len = uint32(size)
|
|
||||||
|
|
||||||
// write header
|
|
||||||
l.mu.Lock()
|
|
||||||
defer l.mu.Unlock()
|
|
||||||
err := binary.Write(l.w, binary.BigEndian, p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// write payload
|
|
||||||
if payload != nil {
|
|
||||||
err = binary.Write(l.w, binary.BigEndian, payload)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return l.w.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Libvirt) getResponse(c chan response) (response, error) {
|
func (l *Libvirt) getResponse(c chan response) (response, error) {
|
||||||
resp := <-c
|
resp := <-c
|
||||||
if resp.Status == StatusError {
|
if resp.Status == socket.StatusError {
|
||||||
return resp, decodeError(resp.Payload)
|
return resp, decodeError(resp.Payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,9 +307,15 @@ func encode(data interface{}) ([]byte, error) {
|
|||||||
|
|
||||||
// decodeError extracts an error message from the provider buffer.
|
// decodeError extracts an error message from the provider buffer.
|
||||||
func decodeError(buf []byte) error {
|
func decodeError(buf []byte) error {
|
||||||
var e libvirtError
|
|
||||||
|
|
||||||
dec := xdr.NewDecoder(bytes.NewReader(buf))
|
dec := xdr.NewDecoder(bytes.NewReader(buf))
|
||||||
|
|
||||||
|
e := struct {
|
||||||
|
Code uint32
|
||||||
|
DomainID uint32
|
||||||
|
Padding uint8
|
||||||
|
Message string
|
||||||
|
Level uint32
|
||||||
|
}{}
|
||||||
_, err := dec.Decode(&e)
|
_, err := dec.Decode(&e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -484,12 +324,13 @@ func decodeError(buf []byte) error {
|
|||||||
if strings.Contains(e.Message, "unknown procedure") {
|
if strings.Contains(e.Message, "unknown procedure") {
|
||||||
return ErrUnsupported
|
return ErrUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
// if libvirt returns ERR_OK, ignore the error
|
// if libvirt returns ERR_OK, ignore the error
|
||||||
if checkError(e, errOk) {
|
if ErrorNumber(e.Code) == ErrOk {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return e
|
return Error{Code: uint32(e.Code), Message: e.Message}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eventDecoder decodes an event from a xdr buffer.
|
// eventDecoder decodes an event from a xdr buffer.
|
||||||
@ -499,40 +340,6 @@ func eventDecoder(buf []byte, e interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// pktlen returns the length of an incoming RPC packet. Read errors will
|
|
||||||
// result in a returned response length of 0 and a non-nil error.
|
|
||||||
func pktlen(r io.Reader) (uint32, error) {
|
|
||||||
buf := make([]byte, unsafe.Sizeof(_p.Len))
|
|
||||||
|
|
||||||
// extract the packet's length from the header
|
|
||||||
_, err := io.ReadFull(r, buf)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return binary.BigEndian.Uint32(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractHeader returns the decoded header from an incoming response.
|
|
||||||
func extractHeader(r io.Reader) (*header, error) {
|
|
||||||
buf := make([]byte, unsafe.Sizeof(_p.Header))
|
|
||||||
|
|
||||||
// extract the packet's header from r
|
|
||||||
_, err := io.ReadFull(r, buf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &header{
|
|
||||||
Program: binary.BigEndian.Uint32(buf[0:4]),
|
|
||||||
Version: binary.BigEndian.Uint32(buf[4:8]),
|
|
||||||
Procedure: binary.BigEndian.Uint32(buf[8:12]),
|
|
||||||
Type: binary.BigEndian.Uint32(buf[12:16]),
|
|
||||||
Serial: int32(binary.BigEndian.Uint32(buf[16:20])),
|
|
||||||
Status: binary.BigEndian.Uint32(buf[20:24]),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type typedParamDecoder struct{}
|
type typedParamDecoder struct{}
|
||||||
|
|
||||||
// Decode decodes a TypedParam. These are part of the libvirt spec, and not xdr
|
// Decode decodes a TypedParam. These are part of the libvirt spec, and not xdr
|
||||||
|
26
vendor/github.com/digitalocean/go-libvirt/socket/dialers/already_connected.go
generated
vendored
Normal file
26
vendor/github.com/digitalocean/go-libvirt/socket/dialers/already_connected.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package dialers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AlreadyConnected implements a dialer interface for a connection that was
|
||||||
|
// established prior to initializing the socket object. This exists solely
|
||||||
|
// for backwards compatability with the previous implementation of Libvirt
|
||||||
|
// that took an already established connection.
|
||||||
|
type AlreadyConnected struct {
|
||||||
|
c net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAlreadyConnected is a noop dialer to simply use a connection previously
|
||||||
|
// established. This means any re-dial attempts simply won't work.
|
||||||
|
func NewAlreadyConnected(c net.Conn) AlreadyConnected {
|
||||||
|
return AlreadyConnected{c}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial just returns the connection previously established.
|
||||||
|
// If at some point it is disconnected by the client, this obviously does *not*
|
||||||
|
// re-dial and will simply return the already closed connection.
|
||||||
|
func (a AlreadyConnected) Dial() (net.Conn, error) {
|
||||||
|
return a.c, nil
|
||||||
|
}
|
57
vendor/github.com/digitalocean/go-libvirt/socket/dialers/local.go
generated
vendored
Normal file
57
vendor/github.com/digitalocean/go-libvirt/socket/dialers/local.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package dialers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// defaultSocket specifies the default path to the libvirt unix socket.
|
||||||
|
defaultSocket = "/var/run/libvirt/libvirt-sock"
|
||||||
|
|
||||||
|
// defaultLocalTimeout specifies the default libvirt dial timeout.
|
||||||
|
defaultLocalTimeout = 15 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
// Local implements connecting to a local libvirtd over the unix socket.
|
||||||
|
type Local struct {
|
||||||
|
timeout time.Duration
|
||||||
|
socket string
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalOption is a function for setting local socket options.
|
||||||
|
type LocalOption func(*Local)
|
||||||
|
|
||||||
|
// WithLocalTimeout sets the dial timeout.
|
||||||
|
func WithLocalTimeout(timeout time.Duration) LocalOption {
|
||||||
|
return func(l *Local) {
|
||||||
|
l.timeout = timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSocket sets the path to the local libvirt socket.
|
||||||
|
func WithSocket(socket string) LocalOption {
|
||||||
|
return func(l *Local) {
|
||||||
|
l.socket = socket
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocal is a default dialer to simply connect to a locally running libvirt's
|
||||||
|
// socket.
|
||||||
|
func NewLocal(opts ...LocalOption) *Local {
|
||||||
|
l := &Local{
|
||||||
|
timeout: defaultLocalTimeout,
|
||||||
|
socket: defaultSocket,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial connects to a local socket
|
||||||
|
func (l *Local) Dial() (net.Conn, error) {
|
||||||
|
return net.DialTimeout("unix", l.socket, l.timeout)
|
||||||
|
}
|
61
vendor/github.com/digitalocean/go-libvirt/socket/dialers/remote.go
generated
vendored
Normal file
61
vendor/github.com/digitalocean/go-libvirt/socket/dialers/remote.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package dialers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// defaultRemotePort specifies the default libvirtd port.
|
||||||
|
defaultRemotePort = "16509"
|
||||||
|
|
||||||
|
// defaultRemoteTimeout specifies the default libvirt dial timeout.
|
||||||
|
defaultRemoteTimeout = 20 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
// Remote implements connecting to a remote server's libvirt using tcp
|
||||||
|
type Remote struct {
|
||||||
|
timeout time.Duration
|
||||||
|
host, port string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteOption is a function for setting remote dialer options.
|
||||||
|
type RemoteOption func(*Remote)
|
||||||
|
|
||||||
|
// WithRemoteTimeout sets the dial timeout.
|
||||||
|
func WithRemoteTimeout(timeout time.Duration) RemoteOption {
|
||||||
|
return func(r *Remote) {
|
||||||
|
r.timeout = timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UsePort sets the port to dial for libirt on the target host server.
|
||||||
|
func UsePort(port string) RemoteOption {
|
||||||
|
return func(r *Remote) {
|
||||||
|
r.port = port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRemote is a dialer for connecting to libvirt running on another server.
|
||||||
|
func NewRemote(hostAddr string, opts ...RemoteOption) *Remote {
|
||||||
|
r := &Remote{
|
||||||
|
timeout: defaultRemoteTimeout,
|
||||||
|
host: hostAddr,
|
||||||
|
port: defaultRemotePort,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial connects to libvirt running on another server.
|
||||||
|
func (r *Remote) Dial() (net.Conn, error) {
|
||||||
|
return net.DialTimeout(
|
||||||
|
"tcp",
|
||||||
|
net.JoinHostPort(r.host, r.port),
|
||||||
|
r.timeout,
|
||||||
|
)
|
||||||
|
}
|
376
vendor/github.com/digitalocean/go-libvirt/socket/socket.go
generated
vendored
Normal file
376
vendor/github.com/digitalocean/go-libvirt/socket/socket.go
generated
vendored
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||||
|
)
|
||||||
|
|
||||||
|
const disconnectTimeout = 5 * time.Second
|
||||||
|
|
||||||
|
// request and response statuses
|
||||||
|
const (
|
||||||
|
// StatusOK is always set for method calls or events.
|
||||||
|
// For replies it indicates successful completion of the method.
|
||||||
|
// For streams it indicates confirmation of the end of file on the stream.
|
||||||
|
StatusOK = iota
|
||||||
|
|
||||||
|
// StatusError for replies indicates that the method call failed
|
||||||
|
// and error information is being returned. For streams this indicates
|
||||||
|
// that not all data was sent and the stream has aborted.
|
||||||
|
StatusError
|
||||||
|
|
||||||
|
// StatusContinue is only used for streams.
|
||||||
|
// This indicates that further data packets will be following.
|
||||||
|
StatusContinue
|
||||||
|
)
|
||||||
|
|
||||||
|
// request and response types
|
||||||
|
const (
|
||||||
|
// Call is used when making calls to the remote server.
|
||||||
|
Call = iota
|
||||||
|
|
||||||
|
// Reply indicates a server reply.
|
||||||
|
Reply
|
||||||
|
|
||||||
|
// Message is an asynchronous notification.
|
||||||
|
Message
|
||||||
|
|
||||||
|
// Stream represents a stream data packet.
|
||||||
|
Stream
|
||||||
|
|
||||||
|
// CallWithFDs is used by a client to indicate the request has
|
||||||
|
// arguments with file descriptors.
|
||||||
|
CallWithFDs
|
||||||
|
|
||||||
|
// ReplyWithFDs is used by a server to indicate the request has
|
||||||
|
// arguments with file descriptors.
|
||||||
|
ReplyWithFDs
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dialer is an interface for connecting to libvirt's underlying socket.
|
||||||
|
type Dialer interface {
|
||||||
|
Dial() (net.Conn, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Router is an interface used to route packets to the appropriate clients.
|
||||||
|
type Router interface {
|
||||||
|
Route(*Header, []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Socket represents a libvirt Socket and its connection state
|
||||||
|
type Socket struct {
|
||||||
|
dialer Dialer
|
||||||
|
router Router
|
||||||
|
|
||||||
|
conn net.Conn
|
||||||
|
reader *bufio.Reader
|
||||||
|
writer *bufio.Writer
|
||||||
|
// used to serialize any Socket writes and any updates to conn, r, or w
|
||||||
|
mu *sync.Mutex
|
||||||
|
|
||||||
|
// disconnected is closed when the listen goroutine associated with a
|
||||||
|
// Socket connection has returned.
|
||||||
|
disconnected chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// packet represents a RPC request or response.
|
||||||
|
type packet struct {
|
||||||
|
// Size of packet, in bytes, including length.
|
||||||
|
// Len + Header + Payload
|
||||||
|
Len uint32
|
||||||
|
Header Header
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global packet instance, for use with unsafe.Sizeof()
|
||||||
|
var _p packet
|
||||||
|
|
||||||
|
// Header is a libvirt rpc packet header
|
||||||
|
type Header struct {
|
||||||
|
// Program identifier
|
||||||
|
Program uint32
|
||||||
|
|
||||||
|
// Program version
|
||||||
|
Version uint32
|
||||||
|
|
||||||
|
// Remote procedure identifier
|
||||||
|
Procedure uint32
|
||||||
|
|
||||||
|
// Call type, e.g., Reply
|
||||||
|
Type uint32
|
||||||
|
|
||||||
|
// Call serial number
|
||||||
|
Serial int32
|
||||||
|
|
||||||
|
// Request status, e.g., StatusOK
|
||||||
|
Status uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// New initializes a new type for managing the Socket.
|
||||||
|
func New(dialer Dialer, router Router) *Socket {
|
||||||
|
s := &Socket{
|
||||||
|
dialer: dialer,
|
||||||
|
router: router,
|
||||||
|
disconnected: make(chan struct{}),
|
||||||
|
mu: &sync.Mutex{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// we start with a closed channel since that indicates no connection
|
||||||
|
close(s.disconnected)
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect uses the dialer provided on creation to establish
|
||||||
|
// underlying physical connection to the desired libvirt.
|
||||||
|
func (s *Socket) Connect() error {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
if !s.isDisconnected() {
|
||||||
|
return errors.New("already connected to socket")
|
||||||
|
}
|
||||||
|
conn, err := s.dialer.Dial()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.conn = conn
|
||||||
|
s.reader = bufio.NewReader(conn)
|
||||||
|
s.writer = bufio.NewWriter(conn)
|
||||||
|
s.disconnected = make(chan struct{})
|
||||||
|
|
||||||
|
go s.listenAndRoute()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnect closes the Socket connection to libvirt and waits for the reader
|
||||||
|
// gorouting to shut down.
|
||||||
|
func (s *Socket) Disconnect() error {
|
||||||
|
// just return if we're already disconnected
|
||||||
|
if s.isDisconnected() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.conn.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we wait for the reader to return so as not to avoid it nil
|
||||||
|
// referencing
|
||||||
|
// Put this in a select,
|
||||||
|
// and have it only nil out the conn value if it doesn't fail
|
||||||
|
select {
|
||||||
|
case <-s.disconnected:
|
||||||
|
case <-time.After(disconnectTimeout):
|
||||||
|
return errors.New("timed out waiting for Disconnect cleanup")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnected returns a channel that will be closed once the current
|
||||||
|
// connection is closed. This can happen due to an explicit call to Disconnect
|
||||||
|
// from the client, or due to non-temporary Read or Write errors encountered.
|
||||||
|
func (s *Socket) Disconnected() <-chan struct{} {
|
||||||
|
return s.disconnected
|
||||||
|
}
|
||||||
|
|
||||||
|
// isDisconnected is a non-blocking function to query whether a connection
|
||||||
|
// is disconnected or not.
|
||||||
|
func (s *Socket) isDisconnected() bool {
|
||||||
|
select {
|
||||||
|
case <-s.disconnected:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// listenAndRoute reads packets from the Socket and calls the provided
|
||||||
|
// Router function to route them
|
||||||
|
func (s *Socket) listenAndRoute() {
|
||||||
|
// only returns once it detects a non-temporary error related to the
|
||||||
|
// underlying connection
|
||||||
|
listen(s.reader, s.router)
|
||||||
|
|
||||||
|
// signal any clients listening that the connection has been disconnected
|
||||||
|
close(s.disconnected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// listen processes incoming data and routes
|
||||||
|
// responses to their respective callback handler.
|
||||||
|
func listen(s io.Reader, router Router) {
|
||||||
|
for {
|
||||||
|
// response packet length
|
||||||
|
length, err := pktlen(s)
|
||||||
|
if err != nil {
|
||||||
|
if isTemporary(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// connection is no longer valid, so shutdown
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// response header
|
||||||
|
h, err := extractHeader(s)
|
||||||
|
if err != nil {
|
||||||
|
// invalid packet
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// payload: packet length minus what was previously read
|
||||||
|
size := int(length) - int(unsafe.Sizeof(_p))
|
||||||
|
buf := make([]byte, size)
|
||||||
|
_, err = io.ReadFull(s, buf)
|
||||||
|
if err != nil {
|
||||||
|
// invalid packet
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// route response to caller
|
||||||
|
router.Route(h, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// isTemporary returns true if the error returned from a read is transient.
|
||||||
|
// If the error type is an OpError, check whether the net connection
|
||||||
|
// error condition is temporary (which means we can keep using the
|
||||||
|
// connection).
|
||||||
|
// Errors not of the net.OpError type tend to be things like io.EOF,
|
||||||
|
// syscall.EINVAL, or io.ErrClosedPipe (i.e. all things that
|
||||||
|
// indicate the connection in use is no longer valid.)
|
||||||
|
func isTemporary(err error) bool {
|
||||||
|
opErr, ok := err.(*net.OpError)
|
||||||
|
if ok {
|
||||||
|
return opErr.Temporary()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// pktlen returns the length of an incoming RPC packet. Read errors will
|
||||||
|
// result in a returned response length of 0 and a non-nil error.
|
||||||
|
func pktlen(r io.Reader) (uint32, error) {
|
||||||
|
buf := make([]byte, unsafe.Sizeof(_p.Len))
|
||||||
|
|
||||||
|
// extract the packet's length from the header
|
||||||
|
_, err := io.ReadFull(r, buf)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return binary.BigEndian.Uint32(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractHeader returns the decoded header from an incoming response.
|
||||||
|
func extractHeader(r io.Reader) (*Header, error) {
|
||||||
|
buf := make([]byte, unsafe.Sizeof(_p.Header))
|
||||||
|
|
||||||
|
// extract the packet's header from r
|
||||||
|
_, err := io.ReadFull(r, buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Header{
|
||||||
|
Program: binary.BigEndian.Uint32(buf[0:4]),
|
||||||
|
Version: binary.BigEndian.Uint32(buf[4:8]),
|
||||||
|
Procedure: binary.BigEndian.Uint32(buf[8:12]),
|
||||||
|
Type: binary.BigEndian.Uint32(buf[12:16]),
|
||||||
|
Serial: int32(binary.BigEndian.Uint32(buf[16:20])),
|
||||||
|
Status: binary.BigEndian.Uint32(buf[20:24]),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendPacket sends a packet to libvirt on the socket connection.
|
||||||
|
func (s *Socket) SendPacket(
|
||||||
|
serial int32,
|
||||||
|
proc uint32,
|
||||||
|
program uint32,
|
||||||
|
payload []byte,
|
||||||
|
typ uint32,
|
||||||
|
status uint32,
|
||||||
|
) error {
|
||||||
|
p := packet{
|
||||||
|
Header: Header{
|
||||||
|
Program: program,
|
||||||
|
Version: constants.ProtocolVersion,
|
||||||
|
Procedure: proc,
|
||||||
|
Type: typ,
|
||||||
|
Serial: serial,
|
||||||
|
Status: status,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
size := int(unsafe.Sizeof(p.Len)) + int(unsafe.Sizeof(p.Header))
|
||||||
|
if payload != nil {
|
||||||
|
size += len(payload)
|
||||||
|
}
|
||||||
|
p.Len = uint32(size)
|
||||||
|
|
||||||
|
if s.isDisconnected() {
|
||||||
|
// this mirrors what a lot of net code return on use of a no
|
||||||
|
// longer valid connection
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
err := binary.Write(s.writer, binary.BigEndian, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// write payload
|
||||||
|
if payload != nil {
|
||||||
|
err = binary.Write(s.writer, binary.BigEndian, payload)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.writer.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendStream sends a stream of packets to libvirt on the socket connection.
|
||||||
|
func (s *Socket) SendStream(serial int32, proc uint32, program uint32,
|
||||||
|
stream io.Reader, abort chan bool) error {
|
||||||
|
// Keep total packet length under 4 MiB to follow possible limitation in libvirt server code
|
||||||
|
buf := make([]byte, 4*MiB-unsafe.Sizeof(_p))
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-abort:
|
||||||
|
return s.SendPacket(serial, proc, program, nil, Stream, StatusError)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
n, err := stream.Read(buf)
|
||||||
|
if n > 0 {
|
||||||
|
err2 := s.SendPacket(serial, proc, program, buf[:n], Stream, StatusContinue)
|
||||||
|
if err2 != nil {
|
||||||
|
return err2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
return s.SendPacket(serial, proc, program, nil, Stream, StatusOK)
|
||||||
|
}
|
||||||
|
// keep original error
|
||||||
|
err2 := s.SendPacket(serial, proc, program, nil, Stream, StatusError)
|
||||||
|
if err2 != nil {
|
||||||
|
return err2
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@
|
|||||||
// This module provides different units of measurement to make other
|
// This module provides different units of measurement to make other
|
||||||
// code more readable.
|
// code more readable.
|
||||||
|
|
||||||
package libvirt
|
package socket
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// B - byte
|
// B - byte
|
2
vendor/github.com/digitalocean/go-qemu/qmp/rpc.go
generated
vendored
2
vendor/github.com/digitalocean/go-qemu/qmp/rpc.go
generated
vendored
@ -67,11 +67,11 @@ func (rpc *LibvirtRPCMonitor) Events(ctx context.Context) (<-chan Event, error)
|
|||||||
|
|
||||||
c := make(chan Event)
|
c := make(chan Event)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer close(c)
|
||||||
// process events
|
// process events
|
||||||
for e := range events {
|
for e := range events {
|
||||||
qe, err := qmpEvent(&e)
|
qe, err := qmpEvent(&e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
close(c)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
vendor/github.com/digitalocean/go-qemu/qmp/socket.go
generated
vendored
3
vendor/github.com/digitalocean/go-qemu/qmp/socket.go
generated
vendored
@ -104,6 +104,9 @@ func (mon *SocketMonitor) Disconnect() error {
|
|||||||
atomic.StoreInt32(mon.listeners, 0)
|
atomic.StoreInt32(mon.listeners, 0)
|
||||||
err := mon.c.Close()
|
err := mon.c.Close()
|
||||||
|
|
||||||
|
for range mon.stream {
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
vendor/modules.txt
vendored
10
vendor/modules.txt
vendored
@ -365,14 +365,16 @@ github.com/cyphar/filepath-securejoin
|
|||||||
# github.com/davecgh/go-spew v1.1.1
|
# github.com/davecgh/go-spew v1.1.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/davecgh/go-spew/spew
|
github.com/davecgh/go-spew/spew
|
||||||
# github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1
|
# github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e
|
||||||
## explicit; go 1.14
|
## explicit; go 1.15
|
||||||
github.com/digitalocean/go-libvirt
|
github.com/digitalocean/go-libvirt
|
||||||
github.com/digitalocean/go-libvirt/internal/constants
|
github.com/digitalocean/go-libvirt/internal/constants
|
||||||
github.com/digitalocean/go-libvirt/internal/event
|
github.com/digitalocean/go-libvirt/internal/event
|
||||||
github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2
|
github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2
|
||||||
# github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001
|
github.com/digitalocean/go-libvirt/socket
|
||||||
## explicit; go 1.15
|
github.com/digitalocean/go-libvirt/socket/dialers
|
||||||
|
# github.com/digitalocean/go-qemu v0.0.0-20221209210016-f035778c97f7
|
||||||
|
## explicit; go 1.18
|
||||||
github.com/digitalocean/go-qemu/qmp
|
github.com/digitalocean/go-qemu/qmp
|
||||||
# github.com/disiqueira/gotree/v3 v3.0.2
|
# github.com/disiqueira/gotree/v3 v3.0.2
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
|
Reference in New Issue
Block a user