datapath
The Datapath plugin takes a URI which points to virtual disk data and chooses a Xen datapath implementation: driver domain, blkback implementation and caching strategy.
type debug_info = string
Debug context from the caller
type domain = string
A string representing a Xen domain on the local host. The string is guaranteed to be unique per-domain but it is not guaranteed to take any particular form. It may (for example) be a Xen domain id, a Xen VM uuid or a Xenstore path or anything else chosen by the toolstack. Implementations should not assume the string has any meaning.
type uri = string
A URI representing the means for accessing the volume data. The interpretation of the URI is specific to the implementation. Xapi will choose which implementation to use based on the URI scheme.
type implementation = variant { ... }
The choice of blkback to use.
Constructors:
| Name |
Type |
Description |
Blkback |
string |
use kernel blkback with the given 'params' key |
Tapdisk3 |
string |
use userspace tapdisk3 with the given 'params' key |
Qdisk |
string |
use userspace qemu qdisk with the given 'params' key |
type backend = struct { ... }
A description of which Xen block backend to use. The toolstack needs this to setup the shared memory connection to blkfront in the VM.
Members:
| Name |
Type |
Description |
domain_uuid |
string |
UUID of the domain hosting the backend |
implementation |
implementation |
choice of implementation technology |
Datapath
Xapi will call the functions here on VM start/shutdown/suspend/resume/migrate. Every function is idempotent. Every function takes a domain parameter which allows the implementation to track how many domains are currently using the volume.
open
[open uri persistent] is called before a disk is attached to a VM. If persistent is true then care should be taken to persist all writes to the disk. If persistent is false then the implementation should configure a temporary location for writes so they can be thrown away on [close].
- Definition
- OCaml example
- Python example
| Name |
Direction |
Type |
Description |
dbg |
in |
debug_info |
Debug context from the caller |
uri |
in |
uri |
A URI which represents how to access the volume disk data. |
persistent |
in |
bool |
True means the disk data is persistent and should be preserved when the datapath is closed i.e. when a VM is shutdown or rebooted. False means the data should be thrown away when the VM is shutdown or rebooted. |
Client
(* these directives only needed in a toplevel: *)
#require "xcp-api-client";;
#require "lwt";;
#require "lwt.syntax";;
#require "rpc.unix";;
open S
open Datapath
open Types
module Client = Datapath_client(struct
include Lwt
let rpc call = return (Rpc_client.do_rpc ~content_type:`XML ~path:"/" ~host:"127.0.0.1" ~port:80 call) (* TODO: Rpc_client needs to support Lwt *)
end)
let result = Client._open ~dbg:"string" ~uri:"string" ~persistent:true;;
Server
(* this line only needed in a toplevel: *)
#require "xcp-api-client";;
open S
open Datapath
module Datapath_myimplementation = functor(M: M) -> struct
(* by default every operation will return a 'not implemented' exception *)
include Datapath_skeleton(M)
(* ... *)
let _open x =
let open Types.Datapath.Open in
let open Types in
return (`Ok ())
(* ... *)
end
Client
import xmlrpclib
import xapi
from storage import *
if __name__ == "__main__":
c = xapi.connect()
results = c.Datapath.open({ dbg: "string", uri: "string", persistent: True })
print (repr(results))
Server
import xmlrpclib
import xapi
from storage import *
class Datapath_myimplementation(Datapath_skeleton):
# by default each method will return a Not_implemented error
# ...
def open(self, dbg, uri, persistent):
"""Xapi will call the functions here on VM start/shutdown/suspend/resume/migrate. Every function is idempotent. Every function takes a domain parameter which allows the implementation to track how many domains are currently using the volume."""
result = {}
return result
# ...
attach
[attach uri domain] prepares a connection between the storage named by [uri] and the Xen domain with id [domain]. The return value is the information needed by the Xen toolstack to setup the shared-memory blkfront protocol. Note that the same volume may be simultaneously attached to multiple hosts for example over a migrate. If an implementation needs to perform an explicit handover, then it should implement [activate] and [deactivate]. This function is idempotent.
- Definition
- OCaml example
- Python example
| Name |
Direction |
Type |
Description |
dbg |
in |
debug_info |
Debug context from the caller |
uri |
in |
uri |
A URI which represents how to access the volume disk data. |
domain |
in |
domain |
An opaque string which represents the Xen domain. |
backend |
out |
backend |
The Xen block backend configuration. |
Client
(* these directives only needed in a toplevel: *)
#require "xcp-api-client";;
#require "lwt";;
#require "lwt.syntax";;
#require "rpc.unix";;
open S
open Datapath
open Types
module Client = Datapath_client(struct
include Lwt
let rpc call = return (Rpc_client.do_rpc ~content_type:`XML ~path:"/" ~host:"127.0.0.1" ~port:80 call) (* TODO: Rpc_client needs to support Lwt *)
end)
let result = Client.attach ~dbg:"string" ~uri:"string" ~domain:"string";;
Server
(* this line only needed in a toplevel: *)
#require "xcp-api-client";;
open S
open Datapath
module Datapath_myimplementation = functor(M: M) -> struct
(* by default every operation will return a 'not implemented' exception *)
include Datapath_skeleton(M)
(* ... *)
let attach x =
let open Types.Datapath.Attach in
let open Types in
return (`Ok (Out.({ domain_uuid = "string"; implementation = Blkback "string" })))
(* ... *)
end
Client
import xmlrpclib
import xapi
from storage import *
if __name__ == "__main__":
c = xapi.connect()
results = c.Datapath.attach({ dbg: "string", uri: "string", domain: "string" })
print (repr(results))
Server
import xmlrpclib
import xapi
from storage import *
class Datapath_myimplementation(Datapath_skeleton):
# by default each method will return a Not_implemented error
# ...
def attach(self, dbg, uri, domain):
"""Xapi will call the functions here on VM start/shutdown/suspend/resume/migrate. Every function is idempotent. Every function takes a domain parameter which allows the implementation to track how many domains are currently using the volume."""
result = {}
result["backend"] = { "domain_uuid": "string", "implementation": None }
return result
# ...
activate
[activate uri domain] is called just before a VM needs to read or write its disk. This is an opportunity for an implementation which needs to perform an explicit volume handover to do it. This function is called in the migration downtime window so delays here will be noticeable to users and should be minimised. This function is idempotent.
- Definition
- OCaml example
- Python example
| Name |
Direction |
Type |
Description |
dbg |
in |
debug_info |
Debug context from the caller |
uri |
in |
uri |
A URI which represents how to access the volume disk data. |
domain |
in |
domain |
An opaque string which represents the Xen domain. |
Client
(* these directives only needed in a toplevel: *)
#require "xcp-api-client";;
#require "lwt";;
#require "lwt.syntax";;
#require "rpc.unix";;
open S
open Datapath
open Types
module Client = Datapath_client(struct
include Lwt
let rpc call = return (Rpc_client.do_rpc ~content_type:`XML ~path:"/" ~host:"127.0.0.1" ~port:80 call) (* TODO: Rpc_client needs to support Lwt *)
end)
let result = Client.activate ~dbg:"string" ~uri:"string" ~domain:"string";;
Server
(* this line only needed in a toplevel: *)
#require "xcp-api-client";;
open S
open Datapath
module Datapath_myimplementation = functor(M: M) -> struct
(* by default every operation will return a 'not implemented' exception *)
include Datapath_skeleton(M)
(* ... *)
let activate x =
let open Types.Datapath.Activate in
let open Types in
return (`Ok ())
(* ... *)
end
Client
import xmlrpclib
import xapi
from storage import *
if __name__ == "__main__":
c = xapi.connect()
results = c.Datapath.activate({ dbg: "string", uri: "string", domain: "string" })
print (repr(results))
Server
import xmlrpclib
import xapi
from storage import *
class Datapath_myimplementation(Datapath_skeleton):
# by default each method will return a Not_implemented error
# ...
def activate(self, dbg, uri, domain):
"""Xapi will call the functions here on VM start/shutdown/suspend/resume/migrate. Every function is idempotent. Every function takes a domain parameter which allows the implementation to track how many domains are currently using the volume."""
result = {}
return result
# ...
deactivate
[deactivate uri domain] is called as soon as a VM has finished reading or writing its disk. This is an opportunity for an implementation which needs to perform an explicit volume handover to do it. This function is called in the migration downtime window so delays here will be noticeable to users and should be minimised. This function is idempotent.
- Definition
- OCaml example
- Python example
| Name |
Direction |
Type |
Description |
dbg |
in |
debug_info |
Debug context from the caller |
uri |
in |
uri |
A URI which represents how to access the volume disk data. |
domain |
in |
domain |
An opaque string which represents the Xen domain. |
Client
(* these directives only needed in a toplevel: *)
#require "xcp-api-client";;
#require "lwt";;
#require "lwt.syntax";;
#require "rpc.unix";;
open S
open Datapath
open Types
module Client = Datapath_client(struct
include Lwt
let rpc call = return (Rpc_client.do_rpc ~content_type:`XML ~path:"/" ~host:"127.0.0.1" ~port:80 call) (* TODO: Rpc_client needs to support Lwt *)
end)
let result = Client.deactivate ~dbg:"string" ~uri:"string" ~domain:"string";;
Server
(* this line only needed in a toplevel: *)
#require "xcp-api-client";;
open S
open Datapath
module Datapath_myimplementation = functor(M: M) -> struct
(* by default every operation will return a 'not implemented' exception *)
include Datapath_skeleton(M)
(* ... *)
let deactivate x =
let open Types.Datapath.Deactivate in
let open Types in
return (`Ok ())
(* ... *)
end
Client
import xmlrpclib
import xapi
from storage import *
if __name__ == "__main__":
c = xapi.connect()
results = c.Datapath.deactivate({ dbg: "string", uri: "string", domain: "string" })
print (repr(results))
Server
import xmlrpclib
import xapi
from storage import *
class Datapath_myimplementation(Datapath_skeleton):
# by default each method will return a Not_implemented error
# ...
def deactivate(self, dbg, uri, domain):
"""Xapi will call the functions here on VM start/shutdown/suspend/resume/migrate. Every function is idempotent. Every function takes a domain parameter which allows the implementation to track how many domains are currently using the volume."""
result = {}
return result
# ...
detach
[detach uri domain] is called sometime after a VM has finished reading or writing its disk. This is an opportunity to clean up any resources associated with the disk. This function is called outside the migration downtime window so can be slow without affecting users. This function is idempotent. This function should never fail. If an implementation is unable to perform some cleanup right away then it should queue the action internally. Any error result represents a bug in the implementation.
- Definition
- OCaml example
- Python example
| Name |
Direction |
Type |
Description |
dbg |
in |
debug_info |
Debug context from the caller |
uri |
in |
uri |
A URI which represents how to access the volume disk data. |
domain |
in |
domain |
An opaque string which represents the Xen domain. |
Client
(* these directives only needed in a toplevel: *)
#require "xcp-api-client";;
#require "lwt";;
#require "lwt.syntax";;
#require "rpc.unix";;
open S
open Datapath
open Types
module Client = Datapath_client(struct
include Lwt
let rpc call = return (Rpc_client.do_rpc ~content_type:`XML ~path:"/" ~host:"127.0.0.1" ~port:80 call) (* TODO: Rpc_client needs to support Lwt *)
end)
let result = Client.detach ~dbg:"string" ~uri:"string" ~domain:"string";;
Server
(* this line only needed in a toplevel: *)
#require "xcp-api-client";;
open S
open Datapath
module Datapath_myimplementation = functor(M: M) -> struct
(* by default every operation will return a 'not implemented' exception *)
include Datapath_skeleton(M)
(* ... *)
let detach x =
let open Types.Datapath.Detach in
let open Types in
return (`Ok ())
(* ... *)
end
Client
import xmlrpclib
import xapi
from storage import *
if __name__ == "__main__":
c = xapi.connect()
results = c.Datapath.detach({ dbg: "string", uri: "string", domain: "string" })
print (repr(results))
Server
import xmlrpclib
import xapi
from storage import *
class Datapath_myimplementation(Datapath_skeleton):
# by default each method will return a Not_implemented error
# ...
def detach(self, dbg, uri, domain):
"""Xapi will call the functions here on VM start/shutdown/suspend/resume/migrate. Every function is idempotent. Every function takes a domain parameter which allows the implementation to track how many domains are currently using the volume."""
result = {}
return result
# ...
close
[close uri] is called after a disk is detached and a VM shutdown. This is an opportunity to throw away writes if the disk is not persistent.
- Definition
- OCaml example
- Python example
| Name |
Direction |
Type |
Description |
dbg |
in |
debug_info |
Debug context from the caller |
uri |
in |
uri |
A URI which represents how to access the volume disk data. |
Client
(* these directives only needed in a toplevel: *)
#require "xcp-api-client";;
#require "lwt";;
#require "lwt.syntax";;
#require "rpc.unix";;
open S
open Datapath
open Types
module Client = Datapath_client(struct
include Lwt
let rpc call = return (Rpc_client.do_rpc ~content_type:`XML ~path:"/" ~host:"127.0.0.1" ~port:80 call) (* TODO: Rpc_client needs to support Lwt *)
end)
let result = Client.close ~dbg:"string" ~uri:"string";;
Server
(* this line only needed in a toplevel: *)
#require "xcp-api-client";;
open S
open Datapath
module Datapath_myimplementation = functor(M: M) -> struct
(* by default every operation will return a 'not implemented' exception *)
include Datapath_skeleton(M)
(* ... *)
let close x =
let open Types.Datapath.Close in
let open Types in
return (`Ok ())
(* ... *)
end
Client
import xmlrpclib
import xapi
from storage import *
if __name__ == "__main__":
c = xapi.connect()
results = c.Datapath.close({ dbg: "string", uri: "string" })
print (repr(results))
Server
import xmlrpclib
import xapi
from storage import *
class Datapath_myimplementation(Datapath_skeleton):
# by default each method will return a Not_implemented error
# ...
def close(self, dbg, uri):
"""Xapi will call the functions here on VM start/shutdown/suspend/resume/migrate. Every function is idempotent. Every function takes a domain parameter which allows the implementation to track how many domains are currently using the volume."""
result = {}
return result
# ...
exceptions
| Name |
Type |
Description |
Unimplemented |
string |
The operation has not been implemented |