| | 109 | |
| | 110 | = Overcoming VirtualBox API Limitations = |
| | 111 | |
| | 112 | == Introduction == |
| | 113 | In previous sections, two limitations of the API offered by VirtualBox |
| | 114 | where pointed out. Namely, the inability to directly support the |
| | 115 | execution of command and file copying between the host and the guest. |
| | 116 | While relatively straightforward solutions exist, notably the usage of SSH, |
| | 117 | they raise issues of their own: the guest needs to (properly) configure this |
| | 118 | SSH server. For this to be effective, we obviously need the guest to |
| | 119 | be accessible "from the outside world". This is not always the case, most |
| | 120 | notably if the guest's networking is based on NAT, as it usually -and |
| | 121 | conveniently- is. |
| | 122 | |
| | 123 | Thus, the requirements for a satisfactory solution would include: |
| | 124 | |
| | 125 | * Minimal or no configuration required on the guest side. |
| | 126 | * No assumptions on the network reachability of the guest. That is to say, |
| | 127 | guest should always act as a client. |
| | 128 | |
| | 129 | Additional features to keep in mind: |
| | 130 | |
| | 131 | * Scalability. The solution should account for the execution of an arbitrary |
| | 132 | number of guests on a given host. |
| | 133 | * Technology agnostic: dependencies on any platform/programming |
| | 134 | language/hypervisor should be kept to a minimum or avoided altogether. |
| | 135 | |
| | 136 | |
| | 137 | == Proposed Solution == |
| | 138 | Following Predrag Buncic's advice, I began looking into such a solution based on |
| | 139 | asynchronous message passing. In order to keep the footprint, both on the host and the guest sides, |
| | 140 | the [http://stomp.codehaus.org/Protocol STOMP protocol] |
| | 141 | came to mind. The protocol is simple enough as to have implementations in a |
| | 142 | large number of programming languages, while fulfilling all flexibility needs. Despite its |
| | 143 | simplicity and being relatively unheard of, ActiveMQ supports it out-of-the-box (even though |
| | 144 | it'd be advisable to use something lighter for a broker). |
| | 145 | |
| | 146 | Focusing on the problem at hand, we need to tackle the following problems: |
| | 147 | |
| | 148 | * Command execution on the guest |
| | 149 | * File transfer from the host to the guest |
| | 150 | * File transfer from the guest to the host |
| | 151 | |
| | 152 | The main reason for differentiating between the last two points has to do |
| | 153 | with the no-servers-at-the-guest-side restriction. The file transfer mechanism will not |
| | 154 | be "symmetric". |
| | 155 | |
| | 156 | The following diagram depicts a bird's eye view of the system's architecture: |
| | 157 | [[Image(arch.png)]] |
| | 158 | |
| | 159 | |
| | 160 | === Command Execution === |
| | 161 | Requesting the execution of a program contained in the guest fit nicely into an async. |
| | 162 | message passing infrastructure: a tailored message addressed to the guest we want to |
| | 163 | run the command on is published, processed by this guest and eventually answered back |
| | 164 | with some sort of status (maybe even periodically in order to feedback about progress). |
| | 165 | |
| | 166 | Given the subscription-based nature of the system, several guests can be addressed at |
| | 167 | once by a single host, triggering the execution of commands (or any other action |
| | 168 | covered by this mechanism) in a single go. Note that neither the hosts nor the |
| | 169 | (arbitrary number of) guests need to know how many of the latter conform the system: |
| | 170 | new guest instances need only subscribe to these "broadcasted" messages on their own |
| | 171 | to become part of the overall system. This contributes to the *scalability* of the system. |
| | 172 | |
| | 173 | |
| | 174 | === File Transfers === |
| | 175 | This is a trickier feature: transfers must be bidirectional, yet the guests can only |
| | 176 | act as clients, with -a priori- no knowledge of the hosts' location (remember that the |
| | 177 | only link between host and guest(s) is the broker). |
| | 178 | The proposed solution consists of a simple HTTP server on the host side. The reasons |
| | 179 | to consider HTTP are twofold: |
| | 180 | |
| | 181 | * Bypassing firewalls. Even if this wouldn't usually be an issue -host and guests running |
| | 182 | on the same machine-, HTTP is the less likely protocol to be filtered out by firewalls. |
| | 183 | * Simplicity. It's possible to implement -or reuse- such a server with a small footprint. |
| | 184 | Likewise for the guests' client side. |
| | 185 | |
| | 186 | The only requirement on this HTTP server is that is must accept PUT requests, in order |
| | 187 | for the guests to upload files. |
| | 188 | |
| | 189 | To enable the guests to access this HTTP server, its host and port must be handed to them. |
| | 190 | This is accomplished, how else, by message passing: because host and guests are all subscribed |
| | 191 | to a common broker on a common topic, such information can be published (ie, broadcasted) in |
| | 192 | a way very much similar to the one described in the previous point for commands. Once guests |
| | 193 | have taken notice of the file host (which does *not* have to be the same as the BOINC host), |
| | 194 | file transmission is handled in the same message-oriented way, once the guests |
| | 195 | are aware of the file host details. |
| | 196 | |
| | 197 | |
| | 198 | === The Devil in the Details === |
| | 199 | In the previous argumentations, it was implied that both host and guests were |
| | 200 | already connected to a common broker. This is clearly not the case upon startup. |
| | 201 | Elaborate mechanism might include the use of [http://www.zeroconf.org/ Zeroconf] methods |
| | 202 | such as [http://avahi.org/ avahi] or |
| | 203 | [http://bonjour.macosforge.org/ bonjour], but in principle and for the |
| | 204 | time being, it can be assumed that the broker |
| | 205 | will be accesible to the guest on the IP acting as its default gateway. In the common case |
| | 206 | of a NAT setup for the guests, this IP is configurable at the hypervisor level, corresponding |
| | 207 | to the BOINC host machine. Even if we wanted to balance the load, placing the broker somewhere |
| | 208 | else, an adequate port forwarding mechanism could be setup at the BOINC host side. |
| | 209 | |
| | 210 | As a particularity of VirtualBox NAT system, there is no out-of-the-box connectivity between |
| | 211 | the hypervisor host and the VM (for details, see the VirtualBox Manual, section 6.4). |
| | 212 | Fortunately, VirtualBox includes a port forwarding mechanism that makes it possible to map |
| | 213 | ports on the VM to the hypervisor's host, circumventing this problem. |
| | 214 | On the other hand, there should be no need to forward any port from the VM, as it's |
| | 215 | supposed to perform only client-side operations. |
| | 216 | On the other hand, if other -unrelated- services, such as the CernVM's web-based administration |
| | 217 | mechanism, need be accessed, it's convenient to keep in mind this feature. Details are available |
| | 218 | at the aforementioned VirtualBox Manual, section 6.4.1. |
| | 219 | |
| | 220 | |
| | 221 | === Open Questions === |
| | 222 | * Where should the broker live? Conveniently on the same machine as the hypervisor or on |
| | 223 | a third host? Maybe even a centralized and widely known (ie, standard) one? This last option |
| | 224 | might face congestion problems, though. |
| | 225 | * Broker choice. Full-fledged ([http://activemq.apache.org/ ActiveMQ]) or more limited but lighter? |
| | 226 | (ie, [http://www.germane-software.com/software/Java/Gozirra/ Gozirra]). On this |
| | 227 | question, unless a centralized broker is universally used, the lighter version largely suffices. |
| | 228 | Otherwise, given the high load expected, a more careful choice should be made. |
| | 229 | |
| | 230 | |
| | 231 | == Implementation == |
| | 232 | [http://cernvm.cern.ch/cernvm/ CernVM] has been taken as the base guest system. |
| | 233 | In order to run the developed prototype, the |
| | 234 | following packages need to be installed (by running conary update <package>): |
| | 235 | - subversion |
| | 236 | - gcc |
| | 237 | |
| | 238 | The following python projects (in the following order) |
| | 239 | have to be downloaded and installed using the provided setup.py: |
| | 240 | |
| | 241 | - Zope interfaces (http://www.zope.org/Products/ZopeInterface) |
| | 242 | - twisted (http://twistedmatrix.com) |
| | 243 | - stomper (subversion repository @ http://stomper.googlecode.com/svn ) |
| | 244 | |
| | 245 | This prototype has been implemented in Python, given its cross-platform nature and the suitability |
| | 246 | of the tools/libraries it provides. |
| | 247 | |
| | 248 | === Overview === |
| | 249 | Upon initialization, guests connect to the broker, that's expected to listen on the |
| | 250 | default STOMP port 61613 at the guest's gateway IP. |
| | 251 | Once connected, it "shouts out" he's joined the party, providing a its unique id (see |
| | 252 | following section for details). Upon reception, the BOINC host notes down this unique id for |
| | 253 | further unicast communication (in principle, other guests don't need this information). The |
| | 254 | host acknowledges the new guest (using the STOMP-provided ack mechanisms). |
| | 255 | |
| | 256 | |
| | 257 | === Unique Identification of Guests === |
| | 258 | The preferred way to identify guests is based on [http://tools.ietf.org/html/rfc4122 UUID]. |
| | 259 | Python includes a uuid module since version 2.5. Unfortunately, CernVM ships with version 2.4, |
| | 260 | so the uuid.py file define this module had beed to include "by hand". |
| | 261 | |
| | 262 | === Tailor-made STOMP Messages === |
| | 263 | For command execution: |
| | 264 | {{{ |
| | 265 | HEADERS: |
| | 266 | cmd: cmd-to-execute |
| | 267 | stdout: stdout-file |
| | 268 | stderr: stderr-file |
| | 269 | [shell: shell-to-use] (def: /bin/sh) |
| | 270 | cwd: cwd-to-use |
| | 271 | env: mapping-defining-exec-env |
| | 272 | }}} |
| | 273 | |
| | 274 | {{{ |
| | 275 | BODY: |
| | 276 | VM-RUN-CMD |
| | 277 | }}} |
| | 278 | |
| | 279 | For file transfers: |
| | 280 | The negotiation for the direct connection between the file host and the guest(s) takes |
| | 281 | place using the following message: |
| | 282 | |
| | 283 | Once the guests have this information, the following message format deals with the actual |
| | 284 | file transfer requests: |
| | 285 | |
| | 286 | {{{ |
| | 287 | HEADERS: |
| | 288 | host: file-host-address |
| | 289 | port: file-host-port |
| | 290 | path: path-to-files |
| | 291 | files: list-of-files |
| | 292 | }}} |
| | 293 | |
| | 294 | {{{ |
| | 295 | BODY: |
| | 296 | UP[-TO-HOST] | DOWN[-TO-HOST] |
| | 297 | }}} |
| | 298 | |
| | 299 | |
| | 300 | == Conclusions == |
| | 301 | (TODO) |
| | 302 | |
| | 303 | Note that the described approach is equally valid for any hypervisor, rendering |
| | 304 | it as a candidate for an independent implementation for the aforementioned features |
| | 305 | of command execution and file transference. |
| | 306 | |
| | 307 | |
| | 308 | == Alternatives == |
| | 309 | XMPP? |
| | 310 | |
| | 311 | |