ruby-libvirt 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }