ruby-libvirt 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/libvirt/domain.h CHANGED
@@ -1,9 +1,6 @@
1
1
  #ifndef DOMAIN_H
2
2
  #define DOMAIN_H
3
3
 
4
- extern VALUE c_domain;
5
-
6
- void domain_free(void *d);
7
4
  VALUE domain_new(virDomainPtr d, VALUE conn);
8
5
  virDomainPtr domain_get(VALUE s);
9
6
 
@@ -10,6 +10,7 @@ def have_libvirt_types(types)
10
10
  types.each { |t| have_type(t, "libvirt/libvirt.h") }
11
11
  end
12
12
 
13
+ # older mkmf does not have checking_message, so implement our own here
13
14
  def libvirt_checking_message(target, place = nil, opt = nil)
14
15
  [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
15
16
  if noun
@@ -42,17 +43,48 @@ SRC
42
43
  end
43
44
 
44
45
  def have_libvirt_consts(consts)
45
- consts.each { |c| have_const(c, "libvirt/libvirt.h") }
46
+ consts.each { |c| have_const(c, ["libvirt/libvirt.h", "libvirt/virterror.h"]) }
46
47
  end
47
48
 
48
49
  extension_name = '_libvirt'
49
50
 
50
- dir_config(extension_name)
51
+ # this is a poor-man's dir_config, but is a bit more flexible. In particular,
52
+ # it allows you to specify the exact location of the libvirt.so, as opposed
53
+ # to requiring a lib/ subdirectory. Note that due to the way include files
54
+ # are done within ruby-libvirt, the libvirt header file(s) must be in a libvirt/
55
+ # subdirectory. Also note that if specifying the include directory, the
56
+ # location of the library must also be specified. Finally, note that if neither
57
+ # the include nor the library are specified, the build will attempt to use
58
+ # pkg-config to discover this information.
59
+ #
60
+ # Taking all of the above rules into account, the valid options are either:
61
+ # $ ruby extconf.rb --with-libvirt-include=/home/clalance/libvirt/include \
62
+ # --with-libvirt-lib=/home/clalance/libvirt/src/.libs
63
+ #
64
+ # To specify the location of the include files and the library, or:
65
+ # $ ruby extconf.rb
66
+ #
67
+ # to attempt to use pkg-config to do it automatically from the system files.
68
+ include = with_config("libvirt-include")
69
+ lib = with_config("libvirt-lib")
70
+ if include and lib
71
+ $LIBPATH = [lib] | $LIBPATH
72
+ $CPPFLAGS += "-I" + include
73
+ have_library("virt", "virConnectOpen", "libvirt/libvirt.h")
51
74
 
52
- unless pkg_config("libvirt")
53
- raise "libvirt not found"
75
+ # if we are using custom libvirt libraries, we have to suppress the default
76
+ # library path so have_func() only picks up the custom ones, not the installed
77
+ # ones
78
+ $DEFLIBPATH = []
79
+ elsif (include and not lib) or (not include and lib)
80
+ raise "Must specify both --with-libvirt-include and --with-libvirt-lib, or neither"
81
+ else
82
+ unless pkg_config("libvirt")
83
+ raise "libvirt library not found in default locations"
84
+ end
54
85
  end
55
86
 
87
+
56
88
  libvirt_types = [ 'virNetworkPtr',
57
89
  'virStoragePoolPtr',
58
90
  'virStorageVolPtr',
@@ -64,6 +96,8 @@ libvirt_types = [ 'virNetworkPtr',
64
96
  'virDomainSnapshotPtr',
65
97
  'virDomainJobInfoPtr',
66
98
  'virNodeDevicePtr',
99
+ 'virStreamPtr',
100
+ 'virTypedParameterPtr',
67
101
  ]
68
102
 
69
103
  libvirt_funcs = [ 'virStorageVolWipe',
@@ -102,6 +136,18 @@ libvirt_funcs = [ 'virStorageVolWipe',
102
136
  'virDomainMemoryPeek',
103
137
  'virConnectOpenAuth',
104
138
  'virEventRegisterImpl',
139
+ 'virDomainIsUpdated',
140
+ 'virDomainSetMemoryParameters',
141
+ 'virConnectGetSysinfo',
142
+ 'virDomainSetBlkioParameters',
143
+ 'virDomainSetMemoryFlags',
144
+ 'virDomainGetState',
145
+ 'virDomainOpenConsole',
146
+ 'virDomainMigrate2',
147
+ 'virDomainScreenshot',
148
+ 'virInterfaceChangeBegin',
149
+ 'virStorageVolDownload',
150
+ 'virDomainInjectNMI',
105
151
  ]
106
152
 
107
153
  libvirt_consts = [ 'VIR_MIGRATE_LIVE',
@@ -118,6 +164,7 @@ libvirt_consts = [ 'VIR_MIGRATE_LIVE',
118
164
  'VIR_DUMP_CRASH',
119
165
  'VIR_DUMP_LIVE',
120
166
  'VIR_DOMAIN_DEVICE_MODIFY_CURRENT',
167
+ 'VIR_DOMAIN_DEVICE_MODIFY_LIVE',
121
168
  'VIR_DOMAIN_DEVICE_MODIFY_CONFIG',
122
169
  'VIR_DOMAIN_DEVICE_MODIFY_FORCE',
123
170
  'VIR_INTERFACE_XML_INACTIVE',
@@ -131,12 +178,41 @@ libvirt_consts = [ 'VIR_MIGRATE_LIVE',
131
178
  'VIR_DOMAIN_EVENT_ID_REBOOT',
132
179
  'VIR_DOMAIN_EVENT_ID_RTC_CHANGE',
133
180
  'VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON',
181
+ 'VIR_FROM_VMWARE',
182
+ 'VIR_FROM_AUDIT',
183
+ 'VIR_FROM_SYSINFO',
184
+ 'VIR_FROM_STREAMS',
185
+ 'VIR_FROM_XENAPI',
186
+ 'VIR_FROM_HOOK',
187
+ 'VIR_ERR_HOOK_SCRIPT_FAILED',
188
+ 'VIR_ERR_MIGRATE_PERSIST_FAILED',
189
+ 'VIR_ERR_OPERATION_TIMEOUT',
190
+ 'VIR_ERR_CONFIG_UNSUPPORTED',
191
+ 'VIR_FROM_XENXM',
192
+ 'VIR_ERR_OPERATION_INVALID',
193
+ 'VIR_ERR_NO_SECURITY_MODEL',
194
+ 'VIR_ERR_AUTH_FAILED',
195
+ 'VIR_FROM_PHYP',
196
+ 'VIR_FROM_ESX',
197
+ 'VIR_FROM_ONE',
198
+ 'VIR_FROM_VBOX',
199
+ 'VIR_FROM_LXC',
200
+ 'VIR_FROM_UML',
201
+ 'VIR_FROM_NETWORK',
202
+ 'VIR_FROM_DOMAIN',
203
+ 'VIR_FROM_STATS_LINUX',
204
+ 'VIR_FROM_XEN_INOTIFY',
205
+ 'VIR_FROM_SECURITY',
206
+ 'VIR_DOMAIN_AFFECT_CURRENT',
207
+ 'VIR_DOMAIN_MEM_CURRENT',
208
+ 'VIR_DOMAIN_EVENT_ID_CONTROL_ERROR',
134
209
  ]
135
210
 
136
211
  have_libvirt_types(libvirt_types)
137
212
  have_libvirt_funcs(libvirt_funcs)
138
213
  if find_header("libvirt/libvirt-qemu.h")
139
- have_func("virDomainQemuMonitorCommand", "libvirt/libvirt-qemu.h")
214
+ have_library("virt-qemu", "virDomainQemuMonitorCommand")
215
+ have_func("virDomainQemuMonitorCommand", "libvirt/libvirt-qemu.h")
140
216
  end
141
217
 
142
218
  have_libvirt_consts(libvirt_consts)
@@ -63,7 +63,7 @@ static VALUE libvirt_interface_create(int argc, VALUE *argv, VALUE s) {
63
63
 
64
64
  rb_scan_args(argc, argv, "01", &flags);
65
65
  if (NIL_P(flags))
66
- flags = INT2FIX(0);
66
+ flags = INT2NUM(0);
67
67
 
68
68
  gen_call_void(virInterfaceCreate, conn(s), interface_get(s),
69
69
  NUM2UINT(flags));
@@ -81,7 +81,7 @@ static VALUE libvirt_interface_destroy(int argc, VALUE *argv, VALUE s) {
81
81
 
82
82
  rb_scan_args(argc, argv, "01", &flags);
83
83
  if (NIL_P(flags))
84
- flags = INT2FIX(0);
84
+ flags = INT2NUM(0);
85
85
 
86
86
  gen_call_void(virInterfaceDestroy, conn(s), interface_get(s),
87
87
  NUM2UINT(flags));
@@ -135,7 +135,7 @@ static VALUE libvirt_interface_xml_desc(int argc, VALUE *argv, VALUE s) {
135
135
  rb_scan_args(argc, argv, "01", &flags);
136
136
 
137
137
  if (NIL_P(flags))
138
- flags = INT2FIX(0);
138
+ flags = INT2NUM(0);
139
139
 
140
140
  gen_call_string(virInterfaceGetXMLDesc, conn(s), 1, interface_get(s),
141
141
  NUM2UINT(flags));
@@ -116,7 +116,7 @@ static VALUE libvirt_netw_xml_desc(int argc, VALUE *argv, VALUE s) {
116
116
  rb_scan_args(argc, argv, "01", &flags);
117
117
 
118
118
  if (NIL_P(flags))
119
- flags = INT2FIX(0);
119
+ flags = INT2NUM(0);
120
120
 
121
121
  gen_call_string(virNetworkGetXMLDesc, conn(s), 1, network_get(s),
122
122
  NUM2UINT(flags));
@@ -127,7 +127,7 @@ static VALUE libvirt_nodedevice_xml_desc(int argc, VALUE *argv, VALUE s) {
127
127
  rb_scan_args(argc, argv, "01", &flags);
128
128
 
129
129
  if (NIL_P(flags))
130
- flags = INT2FIX(0);
130
+ flags = INT2NUM(0);
131
131
 
132
132
  gen_call_string(virNodeDeviceGetXMLDesc, conn(s), 1,
133
133
  nodedevice_get(s), NUM2UINT(flags));
@@ -200,6 +200,8 @@ void init_nodedevice()
200
200
  #if HAVE_TYPE_VIRNODEDEVICEPTR
201
201
  c_nodedevice = rb_define_class_under(m_libvirt, "NodeDevice", rb_cObject);
202
202
 
203
+ rb_define_attr(c_nodedevice, "connection", 1, 0);
204
+
203
205
  rb_define_method(c_nodedevice, "name", libvirt_nodedevice_name, 0);
204
206
  rb_define_method(c_nodedevice, "parent", libvirt_nodedevice_parent, 0);
205
207
  rb_define_method(c_nodedevice, "num_of_caps",
@@ -94,7 +94,7 @@ static VALUE libvirt_nwfilter_xml_desc(int argc, VALUE *argv, VALUE s) {
94
94
  rb_scan_args(argc, argv, "01", &flags);
95
95
 
96
96
  if (NIL_P(flags))
97
- flags = INT2FIX(0);
97
+ flags = INT2NUM(0);
98
98
 
99
99
  gen_call_string(virNWFilterGetXMLDesc, conn(s), 1, nwfilter_get(s),
100
100
  NUM2UINT(flags));
data/ext/libvirt/secret.c CHANGED
@@ -93,7 +93,7 @@ static VALUE libvirt_secret_xml_desc(int argc, VALUE *argv, VALUE s) {
93
93
  rb_scan_args(argc, argv, "01", &flags);
94
94
 
95
95
  if (NIL_P(flags))
96
- flags = INT2FIX(0);
96
+ flags = INT2NUM(0);
97
97
 
98
98
  gen_call_string(virSecretGetXMLDesc, conn(s), 1, secret_get(s),
99
99
  NUM2UINT(flags));
@@ -113,7 +113,7 @@ static VALUE libvirt_secret_set_value(int argc, VALUE *argv, VALUE s) {
113
113
  rb_scan_args(argc, argv, "11", &value, &flags);
114
114
 
115
115
  if (NIL_P(flags))
116
- flags = INT2FIX(0);
116
+ flags = INT2NUM(0);
117
117
 
118
118
  StringValue(value);
119
119
 
@@ -141,7 +141,7 @@ static VALUE libvirt_secret_get_value(int argc, VALUE *argv, VALUE s) {
141
141
  rb_scan_args(argc, argv, "01", &flags);
142
142
 
143
143
  if (NIL_P(flags))
144
- flags = INT2FIX(0);
144
+ flags = INT2NUM(0);
145
145
 
146
146
  val = virSecretGetValue(secret, &value_size, NUM2UINT(flags));
147
147
 
@@ -24,6 +24,7 @@
24
24
  #include "common.h"
25
25
  #include "connect.h"
26
26
  #include "extconf.h"
27
+ #include "stream.h"
27
28
 
28
29
  #if HAVE_TYPE_VIRSTORAGEVOLPTR
29
30
  /* this has to be here (as opposed to below with the rest of the volume
@@ -84,7 +85,7 @@ static VALUE libvirt_pool_build(int argc, VALUE *argv, VALUE p) {
84
85
  rb_scan_args(argc, argv, "01", &flags);
85
86
 
86
87
  if (NIL_P(flags))
87
- flags = INT2FIX(0);
88
+ flags = INT2NUM(0);
88
89
 
89
90
  gen_call_void(virStoragePoolBuild, conn(p), pool_get(p), NUM2UINT(flags));
90
91
  }
@@ -113,7 +114,7 @@ static VALUE libvirt_pool_create(int argc, VALUE *argv, VALUE p) {
113
114
  rb_scan_args(argc, argv, "01", &flags);
114
115
 
115
116
  if (NIL_P(flags))
116
- flags = INT2FIX(0);
117
+ flags = INT2NUM(0);
117
118
 
118
119
  gen_call_void(virStoragePoolCreate, conn(p), pool_get(p), NUM2UINT(flags));
119
120
  }
@@ -143,7 +144,7 @@ static VALUE libvirt_pool_delete(int argc, VALUE *argv, VALUE p) {
143
144
  rb_scan_args(argc, argv, "01", &flags);
144
145
 
145
146
  if (NIL_P(flags))
146
- flags = INT2FIX(0);
147
+ flags = INT2NUM(0);
147
148
 
148
149
  gen_call_void(virStoragePoolDelete, conn(p), pool_get(p), NUM2UINT(flags));
149
150
  }
@@ -161,7 +162,7 @@ static VALUE libvirt_pool_refresh(int argc, VALUE *argv, VALUE p) {
161
162
  rb_scan_args(argc, argv, "01", &flags);
162
163
 
163
164
  if (NIL_P(flags))
164
- flags = INT2FIX(0);
165
+ flags = INT2NUM(0);
165
166
 
166
167
  gen_call_void(virStoragePoolRefresh, conn(p), pool_get(p), NUM2UINT(flags));
167
168
  }
@@ -211,7 +212,7 @@ static VALUE libvirt_pool_info(VALUE s) {
211
212
  _E(r < 0, create_error(e_RetrieveError, "virStoragePoolGetInfo", conn(s)));
212
213
 
213
214
  result = rb_class_new_instance(0, NULL, c_storage_pool_info);
214
- rb_iv_set(result, "@state", INT2FIX(info.state));
215
+ rb_iv_set(result, "@state", INT2NUM(info.state));
215
216
  rb_iv_set(result, "@capacity", ULL2NUM(info.capacity));
216
217
  rb_iv_set(result, "@allocation", ULL2NUM(info.allocation));
217
218
  rb_iv_set(result, "@available", ULL2NUM(info.available));
@@ -232,7 +233,7 @@ static VALUE libvirt_pool_xml_desc(int argc, VALUE *argv, VALUE s) {
232
233
  rb_scan_args(argc, argv, "01", &flags);
233
234
 
234
235
  if (NIL_P(flags))
235
- flags = INT2FIX(0);
236
+ flags = INT2NUM(0);
236
237
 
237
238
  gen_call_string(virStoragePoolGetXMLDesc, conn(s), 1, pool_get(s),
238
239
  NUM2UINT(flags));
@@ -433,7 +434,7 @@ static VALUE libvirt_pool_vol_create_xml(int argc, VALUE *argv, VALUE p) {
433
434
  rb_scan_args(argc, argv, "11", &xml, &flags);
434
435
 
435
436
  if (NIL_P(flags))
436
- flags = INT2FIX(0);
437
+ flags = INT2NUM(0);
437
438
 
438
439
  vol = virStorageVolCreateXML(pool_get(p), StringValueCStr(xml),
439
440
  NUM2UINT(flags));
@@ -459,7 +460,7 @@ static VALUE libvirt_pool_vol_create_xml_from(int argc, VALUE *argv, VALUE p) {
459
460
  rb_scan_args(argc, argv, "21", &xml, &cloneval, &flags);
460
461
 
461
462
  if (NIL_P(flags))
462
- flags = INT2FIX(0);
463
+ flags = INT2NUM(0);
463
464
 
464
465
  vol = virStorageVolCreateXMLFrom(pool_get(p), StringValueCStr(xml),
465
466
  vol_get(cloneval), NUM2UINT(flags));
@@ -508,7 +509,7 @@ static VALUE libvirt_vol_delete(int argc, VALUE *argv, VALUE v) {
508
509
  rb_scan_args(argc, argv, "01", &flags);
509
510
 
510
511
  if (NIL_P(flags))
511
- flags = INT2FIX(0);
512
+ flags = INT2NUM(0);
512
513
 
513
514
  gen_call_void(virStorageVolDelete, conn(v), vol_get(v), NUM2UINT(flags));
514
515
  }
@@ -527,7 +528,7 @@ static VALUE libvirt_vol_wipe(int argc, VALUE *argv, VALUE v) {
527
528
  rb_scan_args(argc, argv, "01", &flags);
528
529
 
529
530
  if (NIL_P(flags))
530
- flags = INT2FIX(0);
531
+ flags = INT2NUM(0);
531
532
 
532
533
  gen_call_void(virStorageVolWipe, conn(v), vol_get(v), NUM2UINT(flags));
533
534
  }
@@ -569,7 +570,7 @@ static VALUE libvirt_vol_xml_desc(int argc, VALUE *argv, VALUE v) {
569
570
  rb_scan_args(argc, argv, "01", &flags);
570
571
 
571
572
  if (NIL_P(flags))
572
- flags = INT2FIX(0);
573
+ flags = INT2NUM(0);
573
574
 
574
575
  gen_call_string(virStorageVolGetXMLDesc, conn(v), 1, vol_get(v),
575
576
  NUM2UINT(flags));
@@ -599,6 +600,46 @@ static VALUE libvirt_vol_free(VALUE s) {
599
600
  }
600
601
  #endif
601
602
 
603
+ #if HAVE_VIRSTORAGEVOLDOWNLOAD
604
+ /*
605
+ * call-seq:
606
+ * vol.download(stream, offset, length, flags=0) -> nil
607
+ *
608
+ * Call +virStorageVolDownload+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolDownload]
609
+ * to download the content of a volume as a stream.
610
+ */
611
+ static VALUE libvirt_vol_download(int argc, VALUE *argv, VALUE v) {
612
+ VALUE st, offset, length, flags;
613
+
614
+ rb_scan_args(argc, argv, "31", &st, &offset, &length, &flags);
615
+
616
+ if (NIL_P(flags))
617
+ flags = INT2NUM(0);
618
+
619
+ gen_call_void(virStorageVolDownload, conn(v), vol_get(v), stream_get(st),
620
+ NUM2ULL(offset), NUM2ULL(length), NUM2UINT(flags));
621
+ }
622
+
623
+ /*
624
+ * call-seq:
625
+ * vol.upload(stream, offset, length, flags=0) -> nil
626
+ *
627
+ * Call +virStorageVolUpload+[http://www.libvirt.org/html/libvirt-libvirt.html#virStorageVolUpload]
628
+ * to upload new content to a volume from a stream.
629
+ */
630
+ static VALUE libvirt_vol_upload(int argc, VALUE *argv, VALUE v) {
631
+ VALUE st, offset, length, flags;
632
+
633
+ rb_scan_args(argc, argv, "31", &st, &offset, &length, &flags);
634
+
635
+ if (NIL_P(flags))
636
+ flags = INT2NUM(0);
637
+
638
+ gen_call_void(virStorageVolUpload, conn(v), vol_get(v), stream_get(st),
639
+ NUM2ULL(offset), NUM2ULL(length), NUM2UINT(flags));
640
+ }
641
+ #endif
642
+
602
643
  void init_storage(void) {
603
644
  /*
604
645
  * Class Libvirt::StoragePool and Libvirt::StoragePoolInfo
@@ -614,6 +655,8 @@ void init_storage(void) {
614
655
  c_storage_pool = rb_define_class_under(m_libvirt, "StoragePool",
615
656
  rb_cObject);
616
657
 
658
+ rb_define_attr(c_storage_pool, "connection", 1, 0);
659
+
617
660
  /* virStoragePoolState */
618
661
  rb_define_const(c_storage_pool, "INACTIVE",
619
662
  INT2NUM(VIR_STORAGE_POOL_INACTIVE));
@@ -723,5 +766,11 @@ void init_storage(void) {
723
766
  rb_define_method(c_storage_vol, "xml_desc", libvirt_vol_xml_desc, -1);
724
767
  rb_define_method(c_storage_vol, "path", libvirt_vol_path, 0);
725
768
  rb_define_method(c_storage_vol, "free", libvirt_vol_free, 0);
769
+
770
+ #if HAVE_VIRSTORAGEVOLDOWNLOAD
771
+ rb_define_method(c_storage_vol, "download", libvirt_vol_download, -1);
772
+ rb_define_method(c_storage_vol, "upload", libvirt_vol_upload, -1);
773
+ #endif
774
+
726
775
  #endif
727
776
  }
@@ -0,0 +1,394 @@
1
+ /*
2
+ * stream.c: virStream methods
3
+ *
4
+ * Copyright (C) 2007,2010 Red Hat Inc.
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ */
20
+
21
+ #include <ruby.h>
22
+ #include <libvirt/libvirt.h>
23
+ #include <libvirt/virterror.h>
24
+ #include "common.h"
25
+ #include "connect.h"
26
+ #include "extconf.h"
27
+
28
+ #if HAVE_TYPE_VIRSTREAMPTR
29
+ static VALUE c_stream;
30
+
31
+ static void stream_free(void *s) {
32
+ generic_free(Stream, s);
33
+ }
34
+
35
+ virStreamPtr stream_get(VALUE s) {
36
+ generic_get(Stream, s);
37
+ }
38
+
39
+ VALUE stream_new(virStreamPtr s, VALUE conn) {
40
+ return generic_new(c_stream, s, conn, stream_free);
41
+ }
42
+
43
+ /*
44
+ * call-seq:
45
+ * stream.send(buffer) -> Fixnum
46
+ *
47
+ * Call +virStreamSend+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamSend]
48
+ * to send the data in buffer out to the stream. The return value is the
49
+ * number of bytes sent, which may be less than the size of the buffer. If
50
+ * an error occurred, -1 is returned. If the transmit buffers are full and the
51
+ * stream is marked non-blocking, returns -2.
52
+ */
53
+ static VALUE libvirt_stream_send(VALUE s, VALUE buffer) {
54
+ int ret;
55
+
56
+ StringValue(buffer);
57
+
58
+ ret = virStreamSend(stream_get(s), RSTRING_PTR(buffer),
59
+ RSTRING_LEN(buffer));
60
+ _E(ret == -1, create_error(e_RetrieveError, "virStreamSend", conn(s)));
61
+
62
+ return INT2NUM(ret);
63
+ }
64
+
65
+ struct stream_recv_args {
66
+ int ret;
67
+ char *data;
68
+ };
69
+
70
+ static VALUE stream_recv_array(VALUE input) {
71
+ VALUE result;
72
+ struct stream_recv_args *args = (struct stream_recv_args *)input;
73
+
74
+ result = rb_ary_new();
75
+
76
+ rb_ary_push(result, INT2NUM(args->ret));
77
+ rb_ary_push(result, rb_str_new(args->data, args->ret));
78
+
79
+ return result;
80
+ }
81
+
82
+ /*
83
+ * call-seq:
84
+ * stream.recv(bytes) -> [return_value, data]
85
+ *
86
+ * Call +virStreamRecv+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamRecv]
87
+ * to receive up to bytes amount of data from the stream. The return is an
88
+ * array with two elements; the return code from the virStreamRecv call and
89
+ * the data (as a String) read from the stream. If an error occurred, the
90
+ * return_value is set to -1. If there is no data pending and the stream is
91
+ * marked as non-blocking, return_value is set to -2.
92
+ */
93
+ static VALUE libvirt_stream_recv(VALUE s, VALUE bytes) {
94
+ char *data;
95
+ int ret;
96
+ int exception = 0;
97
+ VALUE result;
98
+ struct stream_recv_args args;
99
+
100
+ data = ALLOC_N(char, NUM2INT(bytes));
101
+
102
+ ret = virStreamRecv(stream_get(s), data, NUM2INT(bytes));
103
+ if (ret == -1) {
104
+ xfree(data);
105
+ rb_exc_raise(create_error(e_RetrieveError, "virStreamRecv", conn(s)));
106
+ }
107
+
108
+ args.ret = ret;
109
+ args.data = data;
110
+ result = rb_protect(stream_recv_array, (VALUE)&args, &exception);
111
+ if (exception) {
112
+ xfree(data);
113
+ rb_jump_tag(exception);
114
+ }
115
+
116
+ xfree(data);
117
+ return result;
118
+ }
119
+
120
+ static int internal_sendall(virStreamPtr st, char *data, size_t nbytes,
121
+ void *opaque) {
122
+ VALUE result;
123
+ VALUE retcode, buffer;
124
+
125
+ result = rb_yield_values(2, (VALUE)opaque, INT2NUM(nbytes));
126
+
127
+ if (TYPE(result) != T_ARRAY)
128
+ rb_raise(rb_eTypeError, "wrong type (expected Array)");
129
+
130
+ if (RARRAY_LEN(result) != 2)
131
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)",
132
+ RARRAY_LEN(result));
133
+
134
+ retcode = rb_ary_entry(result, 0);
135
+ buffer = rb_ary_entry(result, 1);
136
+
137
+ if (NUM2INT(retcode) < 0)
138
+ return NUM2INT(retcode);
139
+
140
+ StringValue(buffer);
141
+
142
+ if (RSTRING_LEN(buffer) > nbytes)
143
+ rb_raise(rb_eArgError, "asked for %d bytes, block returned %d", nbytes,
144
+ RSTRING_LEN(buffer));
145
+
146
+ memcpy(data, RSTRING_PTR(buffer), RSTRING_LEN(buffer));
147
+
148
+ return NUM2INT(retcode);
149
+ }
150
+
151
+ /*
152
+ * call-seq:
153
+ * stream.sendall(opaque=nil){|opaque, nbytes| send block} -> nil
154
+ *
155
+ * Call +virStreamSendAll+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamSendAll]
156
+ * to send the entire data stream. The send block is required and is executed
157
+ * one or more times to send data. Each invocation of the send block yields
158
+ * the opaque data passed into the initial call and the number of bytes this
159
+ * iteration is prepared to handle. The send block should return an array of
160
+ * 2 elements; the first element should be the return code from the block
161
+ * (-1 for error, 0 otherwise), and the second element should be the data
162
+ * that the block prepared to send.
163
+ */
164
+ static VALUE libvirt_stream_sendall(int argc, VALUE *argv, VALUE s) {
165
+ VALUE opaque;
166
+ int ret;
167
+
168
+ if (!rb_block_given_p())
169
+ rb_raise(rb_eRuntimeError, "A block must be provided");
170
+
171
+ rb_scan_args(argc, argv, "01", &opaque);
172
+
173
+ ret = virStreamSendAll(stream_get(s), internal_sendall, (void *)opaque);
174
+ _E(ret < 0, create_error(e_RetrieveError, "virStreamSendAll", conn(s)));
175
+
176
+ return Qnil;
177
+ }
178
+
179
+ static int internal_recvall(virStreamPtr st, const char *buf, size_t nbytes,
180
+ void *opaque) {
181
+ VALUE result;
182
+
183
+ result = rb_yield_values(2, rb_str_new(buf, nbytes), (VALUE)opaque);
184
+
185
+ if (TYPE(result) != T_FIXNUM)
186
+ rb_raise(rb_eArgError, "wrong type (expected an integer)");
187
+
188
+ return NUM2INT(result);
189
+ }
190
+
191
+ /*
192
+ * call-seq:
193
+ * stream.recvall(opaque){|data, opaque| receive block} -> nil
194
+ *
195
+ * Call +virStreamRecvAll+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamRecvAll]
196
+ * to receive the entire data stream. The receive block is required and is
197
+ * called one or more times to receive data. Each invocation of the receive
198
+ * block yields the data received and the opaque data passed into the initial
199
+ * call. The block should return -1 if an error occurred and 0 otherwise.
200
+ */
201
+ static VALUE libvirt_stream_recvall(int argc, VALUE *argv, VALUE s) {
202
+ VALUE opaque;
203
+ int ret;
204
+
205
+ if (!rb_block_given_p())
206
+ rb_raise(rb_eRuntimeError, "A block must be provided");
207
+
208
+ rb_scan_args(argc, argv, "01", &opaque);
209
+
210
+ ret = virStreamRecvAll(stream_get(s), internal_recvall, (void *)opaque);
211
+ _E(ret < 0, create_error(e_RetrieveError, "virStreamRecvAll", conn(s)));
212
+
213
+ return Qnil;
214
+ }
215
+
216
+ static void stream_event_callback(virStreamPtr st, int events, void *opaque) {
217
+ VALUE passthrough = (VALUE)opaque;
218
+ VALUE cb;
219
+ VALUE cb_opaque;
220
+ VALUE news;
221
+ VALUE s;
222
+
223
+ if (TYPE(passthrough) != T_ARRAY)
224
+ rb_raise(rb_eTypeError,
225
+ "wrong domain event lifecycle callback argument type (expected Array)");
226
+
227
+ if (RARRAY_LEN(passthrough) != 3)
228
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 3)",
229
+ RARRAY_LEN(passthrough));
230
+
231
+ cb = rb_ary_entry(passthrough, 0);
232
+ cb_opaque = rb_ary_entry(passthrough, 1);
233
+ s = rb_ary_entry(passthrough, 2);
234
+
235
+ news = stream_new(st, conn_attr(s));
236
+ if (strcmp(rb_obj_classname(cb), "Symbol") == 0)
237
+ rb_funcall(rb_class_of(cb), rb_to_id(cb), 3, news, INT2NUM(events),
238
+ cb_opaque);
239
+ else if (strcmp(rb_obj_classname(cb), "Proc") == 0)
240
+ rb_funcall(cb, rb_intern("call"), 3, news, INT2NUM(events), cb_opaque);
241
+ else
242
+ rb_raise(rb_eTypeError,
243
+ "wrong stream event callback (expected Symbol or Proc)");
244
+ }
245
+
246
+ /*
247
+ * call-seq:
248
+ * stream.event_add_callback(events, callback, opaque=nil) -> nil
249
+ *
250
+ * Call +virStreamEventAddCallback+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamEventAddCallback]
251
+ * to register a callback to be notified when a stream becomes readable or
252
+ * writeable. The events parameter is an integer representing the events the
253
+ * user is interested in; it should be one or more of EVENT_READABLE,
254
+ * EVENT_WRITABLE, EVENT_ERROR, and EVENT_HANGUP, ORed together. The callback
255
+ * can either be a Symbol (that is the name of a method to callback) or a Proc.
256
+ * The callback should accept 3 parameters: a pointer to the Stream object
257
+ * itself, the integer that represents the events that actually occurred, and
258
+ * an opaque pointer that was (optionally) passed into
259
+ * stream.event_add_callback to begin with.
260
+ */
261
+ static VALUE libvirt_stream_event_add_callback(int argc, VALUE *argv, VALUE s) {
262
+ VALUE events;
263
+ VALUE callback;
264
+ VALUE opaque;
265
+ VALUE passthrough;
266
+ int ret;
267
+
268
+ rb_scan_args(argc, argv, "21", &events, &callback, &opaque);
269
+
270
+ if (!is_symbol_or_proc(callback))
271
+ rb_raise(rb_eTypeError, "wrong argument type (expected Symbol or Proc)");
272
+
273
+ passthrough = rb_ary_new();
274
+ rb_ary_store(passthrough, 0, callback);
275
+ rb_ary_store(passthrough, 1, opaque);
276
+ rb_ary_store(passthrough, 2, s);
277
+
278
+ ret = virStreamEventAddCallback(stream_get(s), NUM2INT(events),
279
+ stream_event_callback, (void *)passthrough,
280
+ NULL);
281
+ _E(ret < 0, create_error(e_RetrieveError, "virStreamEventAddCallback",
282
+ conn(s)));
283
+
284
+ return Qnil;
285
+ }
286
+
287
+ /*
288
+ * call-seq:
289
+ * stream.event_update_callback(events) -> nil
290
+ *
291
+ * Call +virStreamEventUpdateCallback+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamEventUpdateCallback]
292
+ * to change the events that the event callback is looking for. The events
293
+ * parameter is an integer representing the events the user is interested in;
294
+ * it should be one or more of EVENT_READABLE, EVENT_WRITABLE, EVENT_ERROR,
295
+ * and EVENT_HANGUP, ORed together.
296
+ */
297
+ static VALUE libvirt_stream_event_update_callback(VALUE s, VALUE events) {
298
+ int ret;
299
+
300
+ ret = virStreamEventUpdateCallback(stream_get(s), NUM2INT(events));
301
+ _E(ret < 0, create_error(e_RetrieveError, "virStreamEventUpdateCallback",
302
+ conn(s)));
303
+
304
+ return Qnil;
305
+ }
306
+
307
+ /*
308
+ * call-seq:
309
+ * stream.event_remove_callback -> nil
310
+ *
311
+ * Call +virStreamEventRemoveCallback+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamEventRemoveCallback]
312
+ * to remove the event callback currently registered to this stream.
313
+ */
314
+ static VALUE libvirt_stream_event_remove_callback(VALUE s) {
315
+ int ret;
316
+
317
+ ret = virStreamEventRemoveCallback(stream_get(s));
318
+ _E(ret < 0, create_error(e_RetrieveError, "virStreamEventRemoveCallback",
319
+ conn(s)));
320
+
321
+ return Qnil;
322
+ }
323
+
324
+ /*
325
+ * call-seq:
326
+ * stream.finish -> nil
327
+ *
328
+ * Call +virStreamFinish+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamFinish]
329
+ * to finish this stream. Finish is typically used when the stream is no
330
+ * longer needed and needs to be cleaned up.
331
+ */
332
+ static VALUE libvirt_stream_finish(VALUE s) {
333
+ gen_call_void(virStreamFinish, conn(s), stream_get(s));
334
+ }
335
+
336
+ /*
337
+ * call-seq:
338
+ * stream.abort -> nil
339
+ *
340
+ * Call +virStreamAbort+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamAbort]
341
+ * to abort this stream. Abort is typically used when something on the stream
342
+ * has failed, and the stream needs to be cleaned up.
343
+ */
344
+ static VALUE libvirt_stream_abort(VALUE s) {
345
+ gen_call_void(virStreamAbort, conn(s), stream_get(s));
346
+ }
347
+
348
+ /*
349
+ * call-seq:
350
+ * stream.free -> nil
351
+ *
352
+ * Call +virStreamFree+[http://www.libvirt.org/html/libvirt-libvirt.html#virStreamFree]
353
+ * to free this stream. The object will no longer be valid after this call.
354
+ */
355
+ static VALUE libvirt_stream_free(VALUE s) {
356
+ gen_call_free(Stream, s);
357
+ }
358
+ #endif
359
+
360
+ /*
361
+ * Class Libvirt::Domain
362
+ */
363
+ void init_stream()
364
+ {
365
+ #if HAVE_TYPE_VIRSTREAMPTR
366
+ c_stream = rb_define_class_under(m_libvirt, "Stream", rb_cObject);
367
+
368
+ rb_define_attr(c_stream, "connection", 1, 0);
369
+
370
+ rb_define_const(c_stream, "NONBLOCK", INT2NUM(VIR_STREAM_NONBLOCK));
371
+
372
+ rb_define_const(c_stream, "EVENT_READABLE",
373
+ INT2NUM(VIR_STREAM_EVENT_READABLE));
374
+ rb_define_const(c_stream, "EVENT_WRITABLE",
375
+ INT2NUM(VIR_STREAM_EVENT_WRITABLE));
376
+ rb_define_const(c_stream, "EVENT_ERROR", INT2NUM(VIR_STREAM_EVENT_ERROR));
377
+ rb_define_const(c_stream, "EVENT_HANGUP", INT2NUM(VIR_STREAM_EVENT_HANGUP));
378
+
379
+ rb_define_method(c_stream, "send", libvirt_stream_send, 1);
380
+ rb_define_method(c_stream, "recv", libvirt_stream_recv, 2);
381
+ rb_define_method(c_stream, "sendall", libvirt_stream_sendall, -1);
382
+ rb_define_method(c_stream, "recvall", libvirt_stream_recvall, -1);
383
+
384
+ rb_define_method(c_stream, "event_add_callback",
385
+ libvirt_stream_event_add_callback, -1);
386
+ rb_define_method(c_stream, "event_update_callback",
387
+ libvirt_stream_event_update_callback, 1);
388
+ rb_define_method(c_stream, "event_remove_callback",
389
+ libvirt_stream_event_remove_callback, 0);
390
+ rb_define_method(c_stream, "finish", libvirt_stream_finish, 0);
391
+ rb_define_method(c_stream, "abort", libvirt_stream_abort, 0);
392
+ rb_define_method(c_stream, "free", libvirt_stream_free, 0);
393
+ #endif
394
+ }