Merge pull request #63 from YorikSar/streams
Add streams support to libvirt RPC API
This commit is contained in:
commit
17c24de803
1
AUTHORS
1
AUTHORS
@ -17,3 +17,4 @@ Simarpreet Singh <simar@linux.com>
|
|||||||
Alexander Polyakov <apolyakov@beget.com>
|
Alexander Polyakov <apolyakov@beget.com>
|
||||||
Amanda Andrade <amanda.andrade@serpro.gov.br>
|
Amanda Andrade <amanda.andrade@serpro.gov.br>
|
||||||
Geoff Hickey <ghickey@digitalocean.com>
|
Geoff Hickey <ghickey@digitalocean.com>
|
||||||
|
Yuriy Taraday <yorik.sar@gmail.com>
|
||||||
|
@ -159,13 +159,21 @@ type Case struct {
|
|||||||
|
|
||||||
// Proc holds information about a libvirt procedure the parser has found.
|
// Proc holds information about a libvirt procedure the parser has found.
|
||||||
type Proc struct {
|
type Proc struct {
|
||||||
Num int64 // The libvirt procedure number.
|
Num int64 // The libvirt procedure number.
|
||||||
Name string // The name of the go func.
|
Name string // The name of the go func.
|
||||||
LVName string // The name of the libvirt proc this wraps.
|
LVName string // The name of the libvirt proc this wraps.
|
||||||
Args []Decl // The contents of the args struct for this procedure.
|
Args []Decl // The contents of the args struct for this procedure.
|
||||||
Ret []Decl // The contents of the ret struct for this procedure.
|
Ret []Decl // The contents of the ret struct for this procedure.
|
||||||
ArgsStruct string // The name of the args struct for this procedure.
|
ArgsStruct string // The name of the args struct for this procedure.
|
||||||
RetStruct string // The name of the ret struct for this procedure.
|
RetStruct string // The name of the ret struct for this procedure.
|
||||||
|
ReadStreamIdx int // The index of read stream in function argument list
|
||||||
|
WriteStreamIdx int // The index of read stream in function argument list
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcMeta holds information from annotations attached to a libvirt procedure
|
||||||
|
type ProcMeta struct {
|
||||||
|
ReadStream int
|
||||||
|
WriteStream int
|
||||||
}
|
}
|
||||||
|
|
||||||
type structStack []*Structure
|
type structStack []*Structure
|
||||||
@ -552,7 +560,31 @@ func AddEnumVal(name, val string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid enum value %v = %v", name, val)
|
return fmt.Errorf("invalid enum value %v = %v", name, val)
|
||||||
}
|
}
|
||||||
return addEnumVal(name, ev)
|
return addEnumVal(name, ev, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEnumValMeta will add a new enum value with attached metadata to the list.
|
||||||
|
// Metadata is parsed from annotations in libvirt RPC description file that are
|
||||||
|
// in block comment preceding every function in enum, it looks like this:
|
||||||
|
// /**
|
||||||
|
// * @generate: both
|
||||||
|
// * @readstream: 1
|
||||||
|
// * @sparseflag: VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM
|
||||||
|
// * @acl: storage_vol:data_read
|
||||||
|
// */
|
||||||
|
// See full description of possible annotations in libvirt's src/remote/remote_protocol.x
|
||||||
|
// at the top of remote_procedure enum.
|
||||||
|
// We're parsing only @readstream and @writestream annotations at the moment.
|
||||||
|
func AddEnumValMeta(name, val, meta string) error {
|
||||||
|
ev, err := parseNumber(val)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid enum value %v = %v", name, val)
|
||||||
|
}
|
||||||
|
metaObj, err := parseMeta(meta)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid metadata for enum value %v: %v", name, err)
|
||||||
|
}
|
||||||
|
return addEnumVal(name, ev, metaObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddEnumAutoVal adds an enum to the list, using the automatically-incremented
|
// AddEnumAutoVal adds an enum to the list, using the automatically-incremented
|
||||||
@ -560,14 +592,14 @@ func AddEnumVal(name, val string) error {
|
|||||||
// explicit value.
|
// explicit value.
|
||||||
func AddEnumAutoVal(name string) error {
|
func AddEnumAutoVal(name string) error {
|
||||||
CurrentEnumVal++
|
CurrentEnumVal++
|
||||||
return addEnumVal(name, CurrentEnumVal)
|
return addEnumVal(name, CurrentEnumVal, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addEnumVal(name string, val int64) error {
|
func addEnumVal(name string, val int64, meta *ProcMeta) error {
|
||||||
goname := constNameTransform(name)
|
goname := constNameTransform(name)
|
||||||
Gen.EnumVals = append(Gen.EnumVals, ConstItem{goname, name, fmt.Sprintf("%d", val)})
|
Gen.EnumVals = append(Gen.EnumVals, ConstItem{goname, name, fmt.Sprintf("%d", val)})
|
||||||
CurrentEnumVal = val
|
CurrentEnumVal = val
|
||||||
addProc(goname, name, val)
|
addProc(goname, name, val, meta)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,12 +616,16 @@ func AddConst(name, val string) error {
|
|||||||
|
|
||||||
// addProc checks an enum value to see if it's a procedure number. If so, we
|
// addProc checks an enum value to see if it's a procedure number. If so, we
|
||||||
// add the procedure to our list for later generation.
|
// add the procedure to our list for later generation.
|
||||||
func addProc(goname, lvname string, val int64) {
|
func addProc(goname, lvname string, val int64, meta *ProcMeta) {
|
||||||
if !strings.HasPrefix(goname, "Proc") {
|
if !strings.HasPrefix(goname, "Proc") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
goname = goname[4:]
|
goname = goname[4:]
|
||||||
proc := &Proc{Num: val, Name: goname, LVName: lvname}
|
proc := &Proc{Num: val, Name: goname, LVName: lvname, ReadStreamIdx: -1, WriteStreamIdx: -1}
|
||||||
|
if meta != nil {
|
||||||
|
proc.ReadStreamIdx = meta.ReadStream
|
||||||
|
proc.WriteStreamIdx = meta.WriteStream
|
||||||
|
}
|
||||||
Gen.Procs = append(Gen.Procs, *proc)
|
Gen.Procs = append(Gen.Procs, *proc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,6 +641,41 @@ func parseNumber(val string) (int64, error) {
|
|||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseMeta parses procedure metadata to simple string mapping
|
||||||
|
func parseMeta(meta string) (*ProcMeta, error) {
|
||||||
|
res := &ProcMeta{
|
||||||
|
ReadStream: -1,
|
||||||
|
WriteStream: -1,
|
||||||
|
}
|
||||||
|
for _, line := range strings.Split(meta, "\n") {
|
||||||
|
atInd := strings.Index(line, "@")
|
||||||
|
if atInd == -1 {
|
||||||
|
// Should be only first and last line of comment
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
spl := strings.SplitN(line[atInd+1:], ":", 2)
|
||||||
|
if len(spl) != 2 {
|
||||||
|
return nil, fmt.Errorf("invalid annotation: %s", meta)
|
||||||
|
}
|
||||||
|
spl[1] = strings.Trim(spl[1], " ")
|
||||||
|
switch spl[0] {
|
||||||
|
case "readstream":
|
||||||
|
var err error
|
||||||
|
res.ReadStream, err = strconv.Atoi(spl[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid value for readstream: %s", spl[1])
|
||||||
|
}
|
||||||
|
case "writestream":
|
||||||
|
var err error
|
||||||
|
res.WriteStream, err = strconv.Atoi(spl[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid value for writestream: %s", spl[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
// StartStruct is called from the parser when a struct definition is found, but
|
// StartStruct is called from the parser when a struct definition is found, but
|
||||||
// before the member declarations are processed.
|
// before the member declarations are processed.
|
||||||
func StartStruct(name string) {
|
func StartStruct(name string) {
|
||||||
|
@ -259,12 +259,19 @@ func lexText(l *Lexer) stateFn {
|
|||||||
|
|
||||||
// lexBlockComment is used when we find a comment marker '/*' in the input.
|
// lexBlockComment is used when we find a comment marker '/*' in the input.
|
||||||
func lexBlockComment(l *Lexer) stateFn {
|
func lexBlockComment(l *Lexer) stateFn {
|
||||||
|
// Double star is used only at the start of metadata comments
|
||||||
|
metadataComment := strings.HasPrefix(l.input[l.pos:], "/**")
|
||||||
for {
|
for {
|
||||||
if strings.HasPrefix(l.input[l.pos:], "*/") {
|
if strings.HasPrefix(l.input[l.pos:], "*/") {
|
||||||
// Found the end. Advance past the '*/' and discard the comment body.
|
// Found the end. Advance past the '*/' and discard the comment body
|
||||||
|
// unless it's a metadata comment
|
||||||
l.next()
|
l.next()
|
||||||
l.next()
|
l.next()
|
||||||
l.ignore()
|
if metadataComment {
|
||||||
|
l.emit(METADATACOMMENT)
|
||||||
|
} else {
|
||||||
|
l.ignore()
|
||||||
|
}
|
||||||
return lexText
|
return lexText
|
||||||
}
|
}
|
||||||
if l.next() == eof {
|
if l.next() == eof {
|
||||||
|
@ -23,6 +23,7 @@ package libvirt
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/davecgh/go-xdr/xdr2"
|
"github.com/davecgh/go-xdr/xdr2"
|
||||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||||
@ -126,9 +127,15 @@ func decodeTypedParams(dec *xdr.Decoder) ([]TypedParam, error) {
|
|||||||
return params, nil
|
return params, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
{{range .Procs}}
|
{{range $proc := .Procs}}
|
||||||
// {{.Name}} is the go wrapper for {{.LVName}}.
|
// {{.Name}} is the go wrapper for {{.LVName}}.
|
||||||
func (l *Libvirt) {{.Name}}({{range $ix, $arg := .Args}}{{if $ix}}, {{end}}{{.Name}} {{.Type}}{{end}}) ({{range .Ret}}r{{.Name}} {{.Type}}, {{end}}err error) {
|
func (l *Libvirt) {{.Name}}(
|
||||||
|
{{- range $ix, $arg := .Args}}
|
||||||
|
{{- if (eq $ix $proc.WriteStreamIdx)}}{{if $ix}}, {{end}}outStream io.Reader{{end}}
|
||||||
|
{{- if (eq $ix $proc.ReadStreamIdx)}}{{if $ix}}, {{end}}inStream io.Writer{{end}}
|
||||||
|
{{- if $ix}}, {{end}}{{.Name}} {{.Type}}
|
||||||
|
{{- end -}}
|
||||||
|
) ({{range .Ret}}r{{.Name}} {{.Type}}, {{end}}err error) {
|
||||||
var buf []byte
|
var buf []byte
|
||||||
{{if .ArgsStruct}}
|
{{if .ArgsStruct}}
|
||||||
args := {{.ArgsStruct}} {
|
args := {{.ArgsStruct}} {
|
||||||
@ -141,7 +148,10 @@ func (l *Libvirt) {{.Name}}({{range $ix, $arg := .Args}}{{if $ix}}, {{end}}{{.Na
|
|||||||
}
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .RetStruct}} var r response{{end}}
|
{{if .RetStruct}} var r response{{end}}
|
||||||
{{if .RetStruct}}r{{else}}_{{end}}, err = l.request({{.Num}}, constants.Program, buf)
|
{{if .RetStruct}}r{{else}}_{{end}}, err = l.requestStream({{.Num}}, constants.Program, buf,
|
||||||
|
{{- if (ne .WriteStreamIdx -1)}} outStream,{{else}} nil,{{end}}
|
||||||
|
{{- if (ne .ReadStreamIdx -1)}} inStream{{else}} nil{{end -}}
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ import (
|
|||||||
%token IDENTIFIER CONSTANT ERROR
|
%token IDENTIFIER CONSTANT ERROR
|
||||||
// RPCL additional tokens:
|
// RPCL additional tokens:
|
||||||
%token PROGRAM VERSION
|
%token PROGRAM VERSION
|
||||||
|
%token METADATACOMMENT
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@ -99,6 +100,13 @@ enum_value
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
| METADATACOMMENT enum_value_ident '=' value {
|
||||||
|
err := AddEnumValMeta($2.val, $4.val, $1.val)
|
||||||
|
if err != nil {
|
||||||
|
yylex.Error(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
| enum_value_ident '=' value {
|
| enum_value_ident '=' value {
|
||||||
err := AddEnumVal($1.val, $3.val)
|
err := AddEnumVal($1.val, $3.val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -59,6 +59,7 @@ const CONSTANT = 57366
|
|||||||
const ERROR = 57367
|
const ERROR = 57367
|
||||||
const PROGRAM = 57368
|
const PROGRAM = 57368
|
||||||
const VERSION = 57369
|
const VERSION = 57369
|
||||||
|
const METADATACOMMENT = 57370
|
||||||
|
|
||||||
var yyToknames = [...]string{
|
var yyToknames = [...]string{
|
||||||
"$end",
|
"$end",
|
||||||
@ -88,6 +89,7 @@ var yyToknames = [...]string{
|
|||||||
"ERROR",
|
"ERROR",
|
||||||
"PROGRAM",
|
"PROGRAM",
|
||||||
"VERSION",
|
"VERSION",
|
||||||
|
"METADATACOMMENT",
|
||||||
"';'",
|
"';'",
|
||||||
"'{'",
|
"'{'",
|
||||||
"'}'",
|
"'}'",
|
||||||
@ -108,7 +110,7 @@ const yyEofCode = 1
|
|||||||
const yyErrCode = 2
|
const yyErrCode = 2
|
||||||
const yyInitialStackSize = 16
|
const yyInitialStackSize = 16
|
||||||
|
|
||||||
//line sunrpc.y:259
|
//line sunrpc.y:267
|
||||||
|
|
||||||
//line yacctab:1
|
//line yacctab:1
|
||||||
var yyExca = [...]int{
|
var yyExca = [...]int{
|
||||||
@ -119,106 +121,107 @@ var yyExca = [...]int{
|
|||||||
|
|
||||||
const yyPrivate = 57344
|
const yyPrivate = 57344
|
||||||
|
|
||||||
const yyLast = 148
|
const yyLast = 153
|
||||||
|
|
||||||
var yyAct = [...]int{
|
var yyAct = [...]int{
|
||||||
|
|
||||||
84, 77, 36, 111, 103, 76, 61, 67, 32, 129,
|
86, 79, 36, 115, 107, 78, 62, 32, 68, 55,
|
||||||
55, 126, 128, 100, 37, 117, 85, 86, 78, 63,
|
57, 133, 130, 132, 104, 121, 87, 88, 80, 64,
|
||||||
98, 97, 73, 31, 74, 69, 131, 115, 71, 89,
|
37, 102, 75, 31, 76, 101, 114, 135, 119, 72,
|
||||||
41, 94, 72, 62, 40, 10, 39, 43, 42, 13,
|
92, 41, 97, 89, 63, 40, 10, 39, 43, 42,
|
||||||
30, 118, 14, 38, 107, 48, 49, 50, 51, 47,
|
13, 73, 30, 14, 38, 122, 48, 49, 50, 51,
|
||||||
90, 11, 79, 64, 10, 70, 106, 96, 13, 54,
|
47, 111, 93, 81, 71, 11, 110, 138, 10, 65,
|
||||||
12, 14, 52, 29, 134, 127, 119, 108, 91, 75,
|
99, 54, 13, 52, 12, 14, 29, 131, 123, 74,
|
||||||
80, 15, 16, 110, 87, 88, 85, 86, 59, 60,
|
77, 112, 94, 59, 82, 15, 90, 91, 58, 70,
|
||||||
63, 93, 83, 48, 49, 50, 51, 92, 95, 58,
|
16, 64, 85, 96, 87, 88, 60, 61, 95, 84,
|
||||||
82, 27, 25, 23, 20, 102, 18, 99, 2, 105,
|
100, 98, 48, 49, 50, 51, 113, 59, 106, 27,
|
||||||
101, 46, 8, 66, 45, 7, 109, 44, 4, 104,
|
103, 25, 109, 105, 23, 20, 18, 67, 46, 8,
|
||||||
113, 105, 114, 116, 120, 28, 122, 81, 8, 68,
|
108, 45, 7, 44, 4, 109, 2, 120, 124, 117,
|
||||||
123, 7, 26, 124, 4, 121, 125, 112, 130, 53,
|
126, 118, 83, 69, 127, 8, 26, 128, 7, 125,
|
||||||
24, 132, 133, 65, 22, 35, 34, 33, 21, 19,
|
4, 129, 134, 28, 116, 136, 137, 53, 24, 66,
|
||||||
57, 56, 17, 9, 6, 5, 3, 1,
|
22, 35, 34, 33, 21, 19, 56, 17, 9, 6,
|
||||||
|
5, 3, 1,
|
||||||
}
|
}
|
||||||
var yyPact = [...]int{
|
var yyPact = [...]int{
|
||||||
|
|
||||||
45, -1000, -1000, 44, -1000, -1000, -1000, -1000, -1000, -1000,
|
49, -1000, -1000, 51, -1000, -1000, -1000, -1000, -1000, -1000,
|
||||||
73, 71, -1000, 70, 69, 68, 45, 34, -1000, 8,
|
83, 82, -1000, 81, 78, 76, 49, 36, -1000, 9,
|
||||||
-1000, 26, 33, -1000, -1000, -1000, 30, -1000, -1000, 66,
|
-1000, 27, 33, -1000, -1000, -1000, 31, -1000, -1000, 50,
|
||||||
55, -1000, -1000, -1000, -1000, -1000, -4, -1000, 64, -1000,
|
63, -1000, -1000, -1000, -1000, -1000, -4, -1000, 73, -1000,
|
||||||
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
|
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
|
||||||
-1000, -1000, -1000, 89, -2, 25, -3, 0, -1000, -1000,
|
-1000, -1000, -1000, 93, 52, 23, -3, 8, 74, -1000,
|
||||||
-1000, -11, 57, -1000, -1000, 26, -20, 22, 42, 67,
|
-1000, -1000, -12, 58, -1000, -1000, 27, -21, 22, 45,
|
||||||
-1000, 66, 53, 53, -7, -1000, 20, 40, 26, -1,
|
66, -1000, 50, 61, 0, 61, -7, -1000, 21, 43,
|
||||||
-2, 28, -1000, -1000, -1000, -1000, -1000, -13, -16, -1000,
|
27, -1, 52, 30, -1000, -1000, -1000, -1000, -1000, 61,
|
||||||
-1000, 26, -26, 57, 53, -1000, 26, -1000, -1000, -1000,
|
-10, -16, -1000, -1000, 27, -26, 58, 61, -1000, 27,
|
||||||
27, -1000, -1000, 14, 39, 50, 105, -5, 26, -23,
|
-1000, -1000, -1000, -1000, 26, -1000, -1000, 20, 42, 3,
|
||||||
-1000, 11, 38, 53, -1000, 53, -1000, 26, -1000, 105,
|
114, -5, 27, -24, -1000, 14, 39, 61, -1000, 61,
|
||||||
-1000, -29, 37, -27, -1000, -31, 26, -1000, -6, 26,
|
-1000, 27, -1000, 114, -1000, -29, 38, -27, -1000, -30,
|
||||||
-1000, 53, -1000, 36, -1000,
|
27, -1000, -6, 27, -1000, 61, -1000, 28, -1000,
|
||||||
}
|
}
|
||||||
var yyPgo = [...]int{
|
var yyPgo = [...]int{
|
||||||
|
|
||||||
0, 147, 98, 0, 146, 107, 145, 144, 104, 101,
|
0, 152, 116, 0, 151, 113, 150, 149, 111, 108,
|
||||||
143, 142, 10, 141, 140, 139, 138, 1, 8, 137,
|
148, 147, 9, 146, 10, 145, 144, 1, 7, 143,
|
||||||
136, 135, 2, 6, 14, 134, 133, 5, 130, 129,
|
142, 141, 2, 6, 20, 140, 139, 5, 138, 137,
|
||||||
3, 127, 126, 125, 122, 7, 119, 117, 4, 109,
|
3, 134, 131, 129, 126, 8, 123, 122, 4, 110,
|
||||||
106,
|
96,
|
||||||
}
|
}
|
||||||
var yyR1 = [...]int{
|
var yyR1 = [...]int{
|
||||||
|
|
||||||
0, 1, 3, 3, 2, 2, 4, 4, 4, 4,
|
0, 1, 3, 3, 2, 2, 4, 4, 4, 4,
|
||||||
4, 4, 5, 12, 12, 13, 13, 11, 14, 6,
|
4, 4, 5, 12, 12, 13, 13, 13, 11, 14,
|
||||||
6, 15, 16, 7, 17, 17, 17, 17, 18, 22,
|
6, 6, 15, 16, 7, 17, 17, 17, 17, 18,
|
||||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
|
22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||||
24, 24, 24, 24, 23, 19, 20, 20, 21, 26,
|
22, 24, 24, 24, 24, 23, 19, 20, 20, 21,
|
||||||
8, 25, 27, 27, 29, 9, 28, 30, 30, 32,
|
26, 8, 25, 27, 27, 29, 9, 28, 30, 30,
|
||||||
31, 33, 31, 10, 34, 35, 35, 36, 37, 38,
|
32, 31, 33, 31, 10, 34, 35, 35, 36, 37,
|
||||||
38, 39, 40,
|
38, 38, 39, 40,
|
||||||
}
|
}
|
||||||
var yyR2 = [...]int{
|
var yyR2 = [...]int{
|
||||||
|
|
||||||
0, 1, 1, 1, 2, 3, 1, 1, 1, 1,
|
0, 1, 1, 1, 2, 3, 1, 1, 1, 1,
|
||||||
1, 1, 5, 1, 3, 1, 3, 1, 1, 4,
|
1, 1, 5, 1, 3, 1, 4, 3, 1, 1,
|
||||||
4, 1, 0, 3, 1, 1, 1, 1, 2, 1,
|
4, 4, 1, 0, 3, 1, 1, 1, 1, 2,
|
||||||
2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1, 5, 5, 4, 3, 0,
|
1, 1, 1, 1, 1, 1, 5, 5, 4, 3,
|
||||||
6, 1, 2, 3, 0, 10, 1, 2, 3, 0,
|
0, 6, 1, 2, 3, 0, 10, 1, 2, 3,
|
||||||
5, 0, 4, 7, 1, 2, 3, 8, 1, 2,
|
0, 5, 0, 4, 7, 1, 2, 3, 8, 1,
|
||||||
3, 8, 1,
|
2, 3, 8, 1,
|
||||||
}
|
}
|
||||||
var yyChk = [...]int{
|
var yyChk = [...]int{
|
||||||
|
|
||||||
-1000, -1, -2, -4, -5, -6, -7, -8, -9, -10,
|
-1000, -1, -2, -4, -5, -6, -7, -8, -9, -10,
|
||||||
9, 6, 15, 13, 16, 26, 28, -11, 23, -15,
|
9, 6, 15, 13, 16, 26, 29, -11, 23, -15,
|
||||||
23, -16, -25, 23, -28, 23, -34, 23, -2, 29,
|
23, -16, -25, 23, -28, 23, -34, 23, -2, 30,
|
||||||
32, -17, -18, -19, -20, -21, -22, -24, 17, 10,
|
33, -17, -18, -19, -20, -21, -22, -24, 17, 10,
|
||||||
8, 4, 12, 11, -5, -8, -9, 23, 19, 20,
|
8, 4, 12, 11, -5, -8, -9, 23, 19, 20,
|
||||||
21, 22, 29, -29, 29, -12, -13, -14, 23, 23,
|
21, 22, 30, -29, 30, -12, -13, -14, 28, 23,
|
||||||
24, -23, 37, 23, -24, -26, 14, -35, -36, 27,
|
23, 24, -23, 38, 23, -24, -26, 14, -35, -36,
|
||||||
30, 31, 32, 33, 35, -23, -27, -17, 38, 30,
|
27, 31, 32, 33, -14, 34, 36, -23, -27, -17,
|
||||||
28, -37, 23, -12, -3, 23, 24, -3, -3, 36,
|
39, 31, 29, -37, 23, -12, -3, 23, 24, 33,
|
||||||
30, 28, -18, -22, 32, -35, 29, 34, 36, -27,
|
-3, -3, 37, 31, 29, -18, -22, 33, -35, 30,
|
||||||
39, -23, -3, -38, -39, -22, 29, 30, 28, -40,
|
-3, 35, 37, -27, 40, -23, -3, -38, -39, -22,
|
||||||
23, -30, -31, 5, 7, 32, -38, 38, 30, 28,
|
30, 31, 29, -40, 23, -30, -31, 5, 7, 33,
|
||||||
-3, -33, -3, -22, -30, -32, 40, 28, 39, 40,
|
-38, 39, 31, 29, -3, -33, -3, -22, -30, -32,
|
||||||
-17, 32, -17, -3, 28,
|
41, 29, 40, 41, -17, 33, -17, -3, 29,
|
||||||
}
|
}
|
||||||
var yyDef = [...]int{
|
var yyDef = [...]int{
|
||||||
|
|
||||||
0, -2, 1, 0, 6, 7, 8, 9, 10, 11,
|
0, -2, 1, 0, 6, 7, 8, 9, 10, 11,
|
||||||
0, 0, 22, 0, 0, 0, 4, 0, 17, 0,
|
0, 0, 23, 0, 0, 0, 4, 0, 18, 0,
|
||||||
21, 0, 0, 51, 54, 56, 0, 64, 5, 0,
|
22, 0, 0, 52, 55, 57, 0, 65, 5, 0,
|
||||||
0, 23, 24, 25, 26, 27, 0, 29, 0, 31,
|
0, 24, 25, 26, 27, 28, 0, 30, 0, 32,
|
||||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
|
||||||
42, 43, 49, 0, 0, 0, 13, 15, 18, 19,
|
43, 44, 50, 0, 0, 0, 13, 15, 0, 19,
|
||||||
20, 28, 0, 44, 30, 0, 0, 0, 0, 0,
|
20, 21, 29, 0, 45, 31, 0, 0, 0, 0,
|
||||||
12, 0, 0, 0, 0, 48, 0, 0, 0, 0,
|
0, 12, 0, 0, 0, 0, 0, 49, 0, 0,
|
||||||
65, 0, 68, 14, 16, 2, 3, 0, 0, 47,
|
0, 0, 66, 0, 69, 14, 17, 2, 3, 0,
|
||||||
50, 52, 0, 0, 0, 66, 0, 45, 46, 53,
|
0, 0, 48, 51, 53, 0, 0, 0, 67, 0,
|
||||||
0, 28, 63, 0, 0, 0, 0, 0, 69, 0,
|
16, 46, 47, 54, 0, 29, 64, 0, 0, 0,
|
||||||
72, 0, 0, 0, 61, 0, 70, 0, 55, 57,
|
0, 0, 70, 0, 73, 0, 0, 0, 62, 0,
|
||||||
59, 0, 0, 0, 58, 0, 0, 67, 0, 0,
|
71, 0, 56, 58, 60, 0, 0, 0, 59, 0,
|
||||||
62, 0, 60, 0, 71,
|
0, 68, 0, 0, 63, 0, 61, 0, 72,
|
||||||
}
|
}
|
||||||
var yyTok1 = [...]int{
|
var yyTok1 = [...]int{
|
||||||
|
|
||||||
@ -226,21 +229,21 @@ var yyTok1 = [...]int{
|
|||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
38, 39, 37, 3, 31, 3, 3, 3, 3, 3,
|
39, 40, 38, 3, 32, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 40, 28,
|
3, 3, 3, 3, 3, 3, 3, 3, 41, 29,
|
||||||
35, 32, 36, 3, 3, 3, 3, 3, 3, 3,
|
36, 33, 37, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 33, 3, 34, 3, 3, 3, 3, 3, 3,
|
3, 34, 3, 35, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 29, 3, 30,
|
3, 3, 3, 30, 3, 31,
|
||||||
}
|
}
|
||||||
var yyTok2 = [...]int{
|
var yyTok2 = [...]int{
|
||||||
|
|
||||||
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||||
22, 23, 24, 25, 26, 27,
|
22, 23, 24, 25, 26, 27, 28,
|
||||||
}
|
}
|
||||||
var yyTok3 = [...]int{
|
var yyTok3 = [...]int{
|
||||||
0,
|
0,
|
||||||
@ -585,13 +588,13 @@ yydefault:
|
|||||||
|
|
||||||
case 12:
|
case 12:
|
||||||
yyDollar = yyS[yypt-5 : yypt+1]
|
yyDollar = yyS[yypt-5 : yypt+1]
|
||||||
//line sunrpc.y:86
|
//line sunrpc.y:87
|
||||||
{
|
{
|
||||||
StartEnum(yyDollar[2].val)
|
StartEnum(yyDollar[2].val)
|
||||||
}
|
}
|
||||||
case 15:
|
case 15:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:95
|
//line sunrpc.y:96
|
||||||
{
|
{
|
||||||
err := AddEnumAutoVal(yyDollar[1].val)
|
err := AddEnumAutoVal(yyDollar[1].val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -600,8 +603,18 @@ yydefault:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 16:
|
case 16:
|
||||||
|
yyDollar = yyS[yypt-4 : yypt+1]
|
||||||
|
//line sunrpc.y:103
|
||||||
|
{
|
||||||
|
err := AddEnumValMeta(yyDollar[2].val, yyDollar[4].val, yyDollar[1].val)
|
||||||
|
if err != nil {
|
||||||
|
yylex.Error(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 17:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line sunrpc.y:102
|
//line sunrpc.y:110
|
||||||
{
|
{
|
||||||
err := AddEnumVal(yyDollar[1].val, yyDollar[3].val)
|
err := AddEnumVal(yyDollar[1].val, yyDollar[3].val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -609,9 +622,9 @@ yydefault:
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 20:
|
case 21:
|
||||||
yyDollar = yyS[yypt-4 : yypt+1]
|
yyDollar = yyS[yypt-4 : yypt+1]
|
||||||
//line sunrpc.y:124
|
//line sunrpc.y:132
|
||||||
{
|
{
|
||||||
err := AddConst(yyDollar[2].val, yyDollar[4].val)
|
err := AddConst(yyDollar[2].val, yyDollar[4].val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -619,147 +632,147 @@ yydefault:
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 22:
|
case 23:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:138
|
//line sunrpc.y:146
|
||||||
{
|
{
|
||||||
StartTypedef()
|
StartTypedef()
|
||||||
}
|
}
|
||||||
case 28:
|
case 29:
|
||||||
yyDollar = yyS[yypt-2 : yypt+1]
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
//line sunrpc.y:149
|
//line sunrpc.y:157
|
||||||
{
|
{
|
||||||
AddDeclaration(yyDollar[2].val, yyDollar[1].val)
|
AddDeclaration(yyDollar[2].val, yyDollar[1].val)
|
||||||
}
|
}
|
||||||
case 30:
|
case 31:
|
||||||
yyDollar = yyS[yypt-2 : yypt+1]
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
//line sunrpc.y:154
|
//line sunrpc.y:162
|
||||||
{
|
{
|
||||||
yyVAL.val = "u" + yyDollar[2].val
|
yyVAL.val = "u" + yyDollar[2].val
|
||||||
}
|
}
|
||||||
case 31:
|
case 32:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:155
|
//line sunrpc.y:163
|
||||||
{
|
{
|
||||||
yyVAL.val = "float32"
|
yyVAL.val = "float32"
|
||||||
}
|
}
|
||||||
case 32:
|
case 33:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:156
|
//line sunrpc.y:164
|
||||||
{
|
{
|
||||||
yyVAL.val = "float64"
|
yyVAL.val = "float64"
|
||||||
}
|
}
|
||||||
case 33:
|
case 34:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:157
|
//line sunrpc.y:165
|
||||||
{
|
{
|
||||||
yyVAL.val = "bool"
|
yyVAL.val = "bool"
|
||||||
}
|
}
|
||||||
case 34:
|
case 35:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:158
|
//line sunrpc.y:166
|
||||||
{
|
{
|
||||||
yyVAL.val = "string"
|
yyVAL.val = "string"
|
||||||
}
|
}
|
||||||
case 35:
|
case 36:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
|
||||||
//line sunrpc.y:159
|
|
||||||
{
|
|
||||||
yyVAL.val = "byte"
|
|
||||||
}
|
|
||||||
case 40:
|
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:167
|
//line sunrpc.y:167
|
||||||
{
|
{
|
||||||
yyVAL.val = "int64"
|
yyVAL.val = "byte"
|
||||||
}
|
}
|
||||||
case 41:
|
case 41:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:168
|
//line sunrpc.y:175
|
||||||
{
|
{
|
||||||
yyVAL.val = "int32"
|
yyVAL.val = "int64"
|
||||||
}
|
}
|
||||||
case 42:
|
case 42:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:169
|
//line sunrpc.y:176
|
||||||
{
|
{
|
||||||
yyVAL.val = "int16"
|
yyVAL.val = "int32"
|
||||||
}
|
}
|
||||||
case 43:
|
case 43:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:170
|
//line sunrpc.y:177
|
||||||
|
{
|
||||||
|
yyVAL.val = "int16"
|
||||||
|
}
|
||||||
|
case 44:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line sunrpc.y:178
|
||||||
{
|
{
|
||||||
yyVAL.val = "int8"
|
yyVAL.val = "int8"
|
||||||
}
|
}
|
||||||
case 45:
|
case 46:
|
||||||
yyDollar = yyS[yypt-5 : yypt+1]
|
yyDollar = yyS[yypt-5 : yypt+1]
|
||||||
//line sunrpc.y:178
|
//line sunrpc.y:186
|
||||||
{
|
{
|
||||||
AddFixedArray(yyDollar[2].val, yyDollar[1].val, yyDollar[4].val)
|
AddFixedArray(yyDollar[2].val, yyDollar[1].val, yyDollar[4].val)
|
||||||
}
|
}
|
||||||
case 46:
|
case 47:
|
||||||
yyDollar = yyS[yypt-5 : yypt+1]
|
yyDollar = yyS[yypt-5 : yypt+1]
|
||||||
//line sunrpc.y:182
|
//line sunrpc.y:190
|
||||||
{
|
{
|
||||||
AddVariableArray(yyDollar[2].val, yyDollar[1].val, yyDollar[4].val)
|
AddVariableArray(yyDollar[2].val, yyDollar[1].val, yyDollar[4].val)
|
||||||
}
|
}
|
||||||
case 47:
|
case 48:
|
||||||
yyDollar = yyS[yypt-4 : yypt+1]
|
yyDollar = yyS[yypt-4 : yypt+1]
|
||||||
//line sunrpc.y:183
|
//line sunrpc.y:191
|
||||||
{
|
{
|
||||||
AddVariableArray(yyDollar[2].val, yyDollar[1].val, "")
|
AddVariableArray(yyDollar[2].val, yyDollar[1].val, "")
|
||||||
}
|
}
|
||||||
case 48:
|
case 49:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line sunrpc.y:191
|
//line sunrpc.y:199
|
||||||
{
|
{
|
||||||
AddOptValue(yyDollar[3].val, yyDollar[1].val)
|
AddOptValue(yyDollar[3].val, yyDollar[1].val)
|
||||||
}
|
}
|
||||||
case 49:
|
case 50:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line sunrpc.y:195
|
//line sunrpc.y:203
|
||||||
{
|
{
|
||||||
StartStruct(yyDollar[2].val)
|
StartStruct(yyDollar[2].val)
|
||||||
}
|
}
|
||||||
case 50:
|
case 51:
|
||||||
yyDollar = yyS[yypt-6 : yypt+1]
|
yyDollar = yyS[yypt-6 : yypt+1]
|
||||||
//line sunrpc.y:195
|
//line sunrpc.y:203
|
||||||
{
|
{
|
||||||
AddStruct()
|
AddStruct()
|
||||||
}
|
}
|
||||||
case 54:
|
case 55:
|
||||||
yyDollar = yyS[yypt-2 : yypt+1]
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
//line sunrpc.y:208
|
//line sunrpc.y:216
|
||||||
{
|
{
|
||||||
StartUnion(yyDollar[2].val)
|
StartUnion(yyDollar[2].val)
|
||||||
}
|
}
|
||||||
case 55:
|
case 56:
|
||||||
yyDollar = yyS[yypt-10 : yypt+1]
|
yyDollar = yyS[yypt-10 : yypt+1]
|
||||||
//line sunrpc.y:208
|
//line sunrpc.y:216
|
||||||
{
|
{
|
||||||
AddUnion()
|
AddUnion()
|
||||||
}
|
}
|
||||||
case 59:
|
case 60:
|
||||||
yyDollar = yyS[yypt-2 : yypt+1]
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
//line sunrpc.y:221
|
//line sunrpc.y:229
|
||||||
{
|
{
|
||||||
StartCase(yyDollar[2].val)
|
StartCase(yyDollar[2].val)
|
||||||
}
|
}
|
||||||
case 60:
|
case 61:
|
||||||
yyDollar = yyS[yypt-5 : yypt+1]
|
yyDollar = yyS[yypt-5 : yypt+1]
|
||||||
//line sunrpc.y:221
|
//line sunrpc.y:229
|
||||||
{
|
{
|
||||||
AddCase()
|
AddCase()
|
||||||
}
|
}
|
||||||
case 61:
|
case 62:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
//line sunrpc.y:222
|
//line sunrpc.y:230
|
||||||
{
|
{
|
||||||
StartCase("default")
|
StartCase("default")
|
||||||
}
|
}
|
||||||
case 62:
|
case 63:
|
||||||
yyDollar = yyS[yypt-4 : yypt+1]
|
yyDollar = yyS[yypt-4 : yypt+1]
|
||||||
//line sunrpc.y:222
|
//line sunrpc.y:230
|
||||||
{
|
{
|
||||||
AddCase()
|
AddCase()
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
795
libvirt.gen.go
795
libvirt.gen.go
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@
|
|||||||
package libvirt
|
package libvirt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
@ -252,6 +253,58 @@ func TestXMLIntegration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVolumeUploadDownloadIntegration(t *testing.T) {
|
||||||
|
testdata := []byte("Hello, world!")
|
||||||
|
l := New(testConn(t))
|
||||||
|
|
||||||
|
if err := l.Connect(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
defer l.Disconnect()
|
||||||
|
|
||||||
|
pool, err := l.StoragePool("test")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var volObj struct {
|
||||||
|
XMLName xml.Name `xml:"volume"`
|
||||||
|
Name string `xml:"name"`
|
||||||
|
Capacity struct {
|
||||||
|
Value uint64 `xml:",chardata"`
|
||||||
|
} `xml:"capacity"`
|
||||||
|
Target struct {
|
||||||
|
Format struct {
|
||||||
|
Type string `xml:"type,attr"`
|
||||||
|
} `xml:"format"`
|
||||||
|
} `xml:"target"`
|
||||||
|
}
|
||||||
|
volObj.Name = "testvol"
|
||||||
|
volObj.Capacity.Value = uint64(len(testdata))
|
||||||
|
volObj.Target.Format.Type = "raw"
|
||||||
|
xmlVol, err := xml.Marshal(volObj)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
vol, err := l.StorageVolCreateXML(pool, string(xmlVol), 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer l.StorageVolDelete(vol, 0)
|
||||||
|
err = l.StorageVolUpload(vol, bytes.NewBuffer(testdata), 0, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err = l.StorageVolDownload(vol, &buf, 0, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if bytes.Compare(testdata, buf.Bytes()) != 0 {
|
||||||
|
t.Fatal("download not what we uploaded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// verify we're able to concurrently communicate with libvirtd.
|
// verify we're able to concurrently communicate with libvirtd.
|
||||||
// see: https://github.com/digitalocean/go-libvirt/pull/52
|
// see: https://github.com/digitalocean/go-libvirt/pull/52
|
||||||
func Test_concurrentWrite(t *testing.T) {
|
func Test_concurrentWrite(t *testing.T) {
|
||||||
|
118
rpc.go
118
rpc.go
@ -174,10 +174,12 @@ func (l *Libvirt) callback(id uint32, res response) {
|
|||||||
c, ok := l.callbacks[id]
|
c, ok := l.callbacks[id]
|
||||||
l.cm.Unlock()
|
l.cm.Unlock()
|
||||||
if ok {
|
if ok {
|
||||||
|
// we close channel in deregister() so that we don't block here forever without receiver
|
||||||
|
defer func() {
|
||||||
|
recover()
|
||||||
|
}()
|
||||||
c <- res
|
c <- res
|
||||||
}
|
}
|
||||||
|
|
||||||
l.deregister(id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// route sends incoming packets to their listeners.
|
// route sends incoming packets to their listeners.
|
||||||
@ -274,11 +276,107 @@ func (l *Libvirt) deregister(id uint32) {
|
|||||||
// returns response returned by server.
|
// returns response returned by server.
|
||||||
// if response is not OK, decodes error from it and returns it.
|
// if response is not OK, decodes error from it and returns it.
|
||||||
func (l *Libvirt) request(proc uint32, program uint32, payload []byte) (response, error) {
|
func (l *Libvirt) request(proc uint32, program uint32, payload []byte) (response, error) {
|
||||||
|
return l.requestStream(proc, program, payload, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Libvirt) processIncomingStream(c chan response, inStream io.Writer) (response, error) {
|
||||||
|
for {
|
||||||
|
resp, err := l.getResponse(c)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
// StatusOK here means end of stream
|
||||||
|
if resp.Status == StatusOK {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
// StatusError is handled in getResponse, so this is StatusContinue
|
||||||
|
// StatusContinue is valid here only for stream packets
|
||||||
|
// libvirtd breaks protocol and returns StatusContinue with empty Payload when stream finishes
|
||||||
|
if len(resp.Payload) == 0 {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
if inStream != nil {
|
||||||
|
_, err = inStream.Write(resp.Payload)
|
||||||
|
if err != nil {
|
||||||
|
return response{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Libvirt) requestStream(proc uint32, program uint32, payload []byte, outStream io.Reader, inStream io.Writer) (response, error) {
|
||||||
serial := l.serial()
|
serial := l.serial()
|
||||||
c := make(chan response)
|
c := make(chan response)
|
||||||
|
|
||||||
l.register(serial, c)
|
l.register(serial, c)
|
||||||
|
defer l.deregister(serial)
|
||||||
|
|
||||||
|
err := l.sendPacket(serial, proc, program, payload, Call, StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := l.getResponse(c)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if outStream != nil {
|
||||||
|
abortOutStream := make(chan bool)
|
||||||
|
outStreamErr := make(chan error)
|
||||||
|
go func() {
|
||||||
|
outStreamErr <- l.sendStream(serial, proc, program, outStream, abortOutStream)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Even without incoming stream server sends confirmation once all data is received
|
||||||
|
resp, err = l.processIncomingStream(c, inStream)
|
||||||
|
if err != nil {
|
||||||
|
abortOutStream <- true
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = <-outStreamErr
|
||||||
|
if err != nil {
|
||||||
|
return response{}, err
|
||||||
|
}
|
||||||
|
} else if inStream != nil {
|
||||||
|
return l.processIncomingStream(c, inStream)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Libvirt) sendStream(serial uint32, 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-constants.HeaderSize)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-abort:
|
||||||
|
return l.sendPacket(serial, proc, program, nil, Stream, StatusError)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
n, err := stream.Read(buf)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
if n > 0 {
|
||||||
|
err = l.sendPacket(serial, proc, program, buf[:n], Stream, StatusContinue)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Libvirt) sendPacket(serial uint32, proc uint32, program uint32, payload []byte, typ uint32, status uint32) error {
|
||||||
size := constants.PacketLengthSize + constants.HeaderSize
|
size := constants.PacketLengthSize + constants.HeaderSize
|
||||||
if payload != nil {
|
if payload != nil {
|
||||||
size += len(payload)
|
size += len(payload)
|
||||||
@ -290,9 +388,9 @@ func (l *Libvirt) request(proc uint32, program uint32, payload []byte) (response
|
|||||||
Program: program,
|
Program: program,
|
||||||
Version: constants.ProtocolVersion,
|
Version: constants.ProtocolVersion,
|
||||||
Procedure: proc,
|
Procedure: proc,
|
||||||
Type: Call,
|
Type: typ,
|
||||||
Serial: serial,
|
Serial: serial,
|
||||||
Status: StatusOK,
|
Status: status,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,23 +399,23 @@ func (l *Libvirt) request(proc uint32, program uint32, payload []byte) (response
|
|||||||
defer l.mu.Unlock()
|
defer l.mu.Unlock()
|
||||||
err := binary.Write(l.w, binary.BigEndian, p)
|
err := binary.Write(l.w, binary.BigEndian, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response{}, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// write payload
|
// write payload
|
||||||
if payload != nil {
|
if payload != nil {
|
||||||
err = binary.Write(l.w, binary.BigEndian, payload)
|
err = binary.Write(l.w, binary.BigEndian, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response{}, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := l.w.Flush(); err != nil {
|
return l.w.Flush()
|
||||||
return response{}, err
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
func (l *Libvirt) getResponse(c chan response) (response, error) {
|
||||||
resp := <-c
|
resp := <-c
|
||||||
if resp.Status != StatusOK {
|
if resp.Status == StatusError {
|
||||||
return resp, decodeError(resp.Payload)
|
return resp, decodeError(resp.Payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
units.go
Normal file
27
units.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2016 The go-libvirt Authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// This module provides different units of measurement to make other
|
||||||
|
// code more readable.
|
||||||
|
|
||||||
|
package libvirt
|
||||||
|
|
||||||
|
const (
|
||||||
|
// B - byte
|
||||||
|
B = 1
|
||||||
|
// KiB - kibibyte
|
||||||
|
KiB = 1024 * B
|
||||||
|
// MiB - mebibyte
|
||||||
|
MiB = 1024 * KiB
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user