To develop the Xenapi Admin Tools for the Xenapi Admin Project I install git on the XCP/Xenserver host so I can write tools and keep the github project up to date as well. Following is how to get git working on XCP 1.6 - Xenserver 6.5.  To develop tools I just mount my XCP host /partition on my development machine via sshfs so I can edit tools remotely. When I'm satisfied with the tools I commit them using git commit -a  followed by git push to send the changes to the xenapi-admin-tools github repository.


 Add the EPEL repo, install git then disable the repo

We add the EPEL repo (which is necessary), install git and then disable the repo immediately to keep other system specific packages from updating.

rpm -ivh
yum install git
sed -i 's/enabled=1/enabled=0/g' /etc/yum.repos.d/epel.repo


Configuring git

To use git to clone our Xenapi Admin Tools repository you'll need to set a few configuration items. Change "Your User Name" to your actual username you want to authenticate with. Change "Your Email Address" to your own email address.

git config --global "Your User Name"
git config --global "Your Email Address" git config --global credential.helper cache git config --global credential.helper 'cache --timeout 3600'
git config --global push.default simple


Clone the xenapi-admin-tools github and add it to your PATH (OPTIONAL)

Cloning the github repo is pretty easy. Below we clone the Xenapi Admin Projects tools repo which  will create a /root/xenapi-admin-tools directory. The tools are in xenapi-admin-tools/releases/<version number> but to use them we'll need to add that directory to our system $PATH variable.

cd /root
git clone
echo 'PATH="$PATH:/root/xenapi-admin-tools/releases/4.1"' >> ~/.bashrc 




The Xenapi Admin Tools are starting to  become so useful that I don't like having XCP hosts without them. Currently you can go to and download the archive onto your host, extract it and then copy the tools to your PATH. This however, is a lot of work since they get updated often. In the coming weeks (months?) I'll be finishing the Yum repo for Xenapi Admin Tools so the XCP package manager can keep them up to date. Until I get that accomplished however it may be easier to just install git and clone the github repository. Every time you want to get updates you'd just cd into the xenapi-admin-tools directory and run git pull.


With that in mind we have to add the EPEL repository where git is housed in order to use Yum to install it.


Install the EPEL repo

rpm -ivh


Install git

yum install git


Disable EPEL repo

The EPEL repository is enabled by default so we didn't have to do anything special to install git. However, you may not want it enabled all the time because packages that EPEL hosts may replace XCP specific packages and mess up your system

sed -i 's/enabled=1/enabled=0/g' /etc/yum.repos.d/epel.repo


 On occasion you may want to have access to a VM's Virtual Disk Image from the Control Domain (or another VM). An example of this would be access files in a VM disk that due to corruption will no longer boot. An XCP local Storage Repository is created from an LVM Volume Group. Each Virtual Disk Image represents one Logical Volume. However, mounting the Logical Volume directly isn't possible because there's  VHD (Virtual Hard Drive) container inside the Logical Volume. Inside the VHD is the real VM disk's partitions. The hierarchy goes something like this  Control Domain Volume Group -> Control Domain Logical Volume -> VHD Container -> VM disk -> VM disk physical Volume -> VM Disk Volume Group -> VM Disk Logical Volume -> VM Disk filesystem. You can see there's quite a few layers here but mounting the VM's disk filesystem IS possible. Here's how.

Since the Control Domain is really a VM itself (privileged VM) we can create a Virtual Block Device using the VM's Virtual Disk Image. From there we use kpartx to map the partitions to Control Domain device nodes.


1. Finding VDI UUID number

[root@testcloud1 ~]# xe vbd-list
uuid ( RO)             : b68a332b-4155-f1c4-b224-18fb465dc8e4
          vm-uuid ( RO): fec94868-0449-3616-39b9-08c3b27dab70
    vm-name-label ( RO): Fedora17
         vdi-uuid ( RO): 199619f0-e483-4618-bbd4-bdc9c524bde1
            empty ( RO): false
           device ( RO): 


2. Finding the Control Domain UUID number 

[root@testcloud1 ~]# xe vm-list is-control-domain=true
uuid ( RO)           : 2dfc3f33-4afa-47dd-8af6-21877326f8e4
     name-label ( RW): Control domain on host: testcloud1
    power-state ( RO): running


3. Creating a virtual block device for the VDI on our Control Domain. This returns the VBD UUID. 

[root@testcloud1 ~]# xe vbd-create device=autodetect vm-uuid=2dfc3f33-4afa-47dd-8af6-21877326f8e4   vdi-uuid=199619f0-e483-4618-bbd4-bdc9c524bde1


4. Plugging in the Virtual Block Device gives us a /dev/sm/backend/<sr-uuid>/<vdi-uuid> device which fdisk will list. 

[root@testcloud1 ~]# xe vbd-plug uuid=11740055-f8d4-3d84-1f90-fb1f4b646fd6 


5. Showing the VBD attached to the control domain AND to the Fedora17 VM 

[root@testcloud1 ~]# xe vbd-list 
uuid ( RO)             : b68a332b-4155-f1c4-b224-18fb465dc8e4
          vm-uuid ( RO): fec94868-0449-3616-39b9-08c3b27dab70
    vm-name-label ( RO): Fedora17
         vdi-uuid ( RO): 199619f0-e483-4618-bbd4-bdc9c524bde1
            empty ( RO): false
           device ( RO): 

uuid ( RO)             : 11740055-f8d4-3d84-1f90-fb1f4b646fd6
          vm-uuid ( RO): 2dfc3f33-4afa-47dd-8af6-21877326f8e4
    vm-name-label ( RO): Control domain on host: testcloud1
         vdi-uuid ( RO): 199619f0-e483-4618-bbd4-bdc9c524bde1
            empty ( RO): false
           device ( RO): sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1

6. Showing the Device Node using ls and fdisk

[root@testcloud1 ~]# ls -l /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1
brw------- 1 root root 253, 0 Jan 12 00:52 /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1


[root@testcloud1 ~]# fdisk -l $(ls /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1)

Disk /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

                                                                                     Device Boot      Start         End      Blocks   Id  System
/dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bd  *           1         980     7863296   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bd            980        1045      524288   82  Linux swap / Solaris
[root@testcloud1 ~]# kpartx -a $(ls /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1)
[root@testcloud1 ~]# ls /dev/mapper/


7. Use kpartx to create /dev/mapper entries for each partition.

[root@testcloud1 ~]# kpartx -a $(ls /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1)


8. kpartx creates /dev/mapper nodes

[root@testcloud1 ~]# ls /dev/mapper/


9. Mount the partitions

[root@testcloud1 ~]# mount /dev/mapper/199619f0-e483-4618-bbd4-bdc9c524bde1p1 /media/Fedora17-rootfs/


[root@testcloud1 ~]# ls /media/Fedora17-rootfs/
bin  boot  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var


Notes: Be careful with mounting VDI's from VMs on the Control Domain. Best practice is to make sure that the VDI is not accessible from the Control Domain AND the VM at the same time. Mounting to two locations at once is a great way of corrupting your disk by having two different Operating Systems writing to the disk at the same time.

I've started the process of making Xenapi Admin Tools XCP 1.6 compliant. I haven't found too many things I've had to change but XCP referrs to a few parameters differently. 

For instance the software-version map parameter has changed the product_brand item to platform_name. The item product_version has been changed to platform_version.


XCP 1.1 XCP 1.6
product_brand platform_name
product_version platform_version


Neither of these changes are major and I believe they were made to make XCP more compatible with Xenserver (or at least bring their code into sync) but my lshosts command would bring up nothing for both of those columns. This has been fixed and backwards compatibility has been maintained with XCP 1.1.

Citrix has an opening for a Xen Evangelist. From their blog:

"The Xen Open Source Evangelist will be an advocate for projects (Xen, Xen Cloud Platform and Xen ARM) and be primarily engaged with open source Xen users, upstream and downstream projects of Xen as well as developers of projects. In addition the Open Source Xen Evangelist will be responsible for representing Citrix and explaining their products and services in the appropriate venues."

It goes on to say that the person would demo and speak at key events around the world, communicate with the community, educate people on Xen and encourage the community to contribute to Xen.  
Sounds like an interesting opportunity. For more information apply at the Citrix site


  • A Linux or Windows PC
  • USB Thumbdrive
  • Xenserver ISO image (tested versions)
    • XCP 1.1
    • XCP 1.5/1.6
    • Xenserver 6.2
    • Xenserver 6.5



If you're using Windows you need to download Unetbootin. Most Linux distributions include it in their repositories so you can install it using the standard Linux package managers (yum, apt-get, zypper,synaptic etc.). You will also need to download the Xenserver installation CD and save it. 


Setting up the USB thumb drive

The USB thumbdrive has to have a partition on it and it has to be formatted as FAT32. 


  1. Make yourself root using su or sudo.
  2. fdisk <device>
  3. Create a new partition and change the partition type to vfat
  4. Save the partition
  5. Format it using mkfs -t vfat <device>

















Installing XCP/Xenserver on the thumbdrive

  1. Mount the partition with the mount command or just remove the thumb drive and reinsert it (usually works)
  2. Start unetbootin
  3. Select Diskimage and then your XCP/Xenserver ISO image that you downloaded
  4. Select USB Drive under Type
  5. Select your thumb drive device
  6. Press OK




















Fixing the thumbdrive so it will boot properly

The isolinux is used to boot ISO9660 disks like cdroms. We need to change the config so it uses syslinux which is used to boot hard disks.

cd into your mounted thumbdrive and copy/paste the following commands

mv boot/isolinux/isolinux.cfg boot/isolinux/syslinux.cfg
mv boot/isolinux boot/syslinux
mv syslinux.cfg syslinux.cfg.bak









You're done. Insert the thumbdrive into your future XCP/Xenserver host and reboot. You may need to go into the BIOS to change the boot order so it will boot from a USB device.


  1. Although I mentioned you can do this from Windows I won't be providing any support for it because I don't use Windows
  2. The thumbdrive needs to be formatted as FAT32 only
  3. Unetbootin has a tendency to just add files to the thumbdrive so make sure you format the thumbdrive between uses
  4. Not renaming the syslinux/isolinux files will get you an Unfound kernel error on boot


A common error is getting the dreaded mboot.c32: not a COM32R image  message. This seems to be because on some versions of the XCP install media the mboot.c32 file is not quite right. The last time I had to fix this I created a Xenserver 6.2 USB thumbdrive (which worked) and copied the /boot/syslinux/mboot.c32 file from there into my XCP 1.1 USB thumbdrive (which got the error listed above). Copy the good mboot.c32 file to the USB thumbdrive's /boot/syslinux folder. This solved the problem for me and so far I've only had it with XCP 1.1.

Xenserver 6.2 - 6.5 doesn't seem to have the problem listed above.

/*! * @mekwall's .vangogh() for Syntax Highlighting * * All code is open source and dual licensed under GPL and MIT. * Check the individual licenses for more information. * * */ (function($,a,b){var c=1,d=!1,e=!1,f={get:function(b){var c=a.location.hash;if(c.length>0){var d=c.match(new RegExp(b+":{([a-zA-Z0-9,-]*)}"));if(d)return d[1].split(",")}return[]},set:function(b,c){var d=a.location.hash,e,f=b+":{"+c.join(",")+"}",g=d.indexOf(b+":{");if(c.length===0)return this.remove(b);g!==-1?e=d.replace(new RegExp("("+b+":{[a-zA-Z0-9,-]*})"),f):e=d.length>0?d+","+f:f,a.location.hash=e},remove:function(b){a.location.hash=a.location.hash.replace(new RegExp("([,]?"+b+":{[a-zA-Z0-9,-]*}[,]?)"),"")}},g={numberRange:/^([0-9]+)-([0-9]+)$/,pageNumber:/-([0-9]+)$/,multilineBegin:/(?:.[^<]*(?!<\/span>)|)$/ig,multilineEnd:/()?(?:.[^<]*)?(<\/span>)/ig};$.fn.vanGogh=function(h){function n(){if(d||e)setTimeout(n,100);else{k++;if(k>=10)return;if(h.source&&!l){e=!0,$.ajax({url:h.source,crossDomain:!0,dataType:"text",success:function(a){l=a},error:function(a,b){l="ERROR: "+b},complete:function(){e=!1,n()}});return}b=b||a.hljs;if(!b){d=!0,$.getScript(h.autoload,function(){d=!1,n()});return}j.filter("pre,code").each(function(){function r(b,c,e){var h=!1,i=a.find(".vg-line");c&&(a.find(".vg-highlight").removeClass("vg-highlight"),f.remove(d),k=[]),b=$.type(b)==="array"?b:[b],$.each(b,function(b,c){if(k.indexOf(c)<=-1){!isNaN(parseFloat(c,10))&&isFinite(c)&&(c=parseInt(c,10));if($.type(c)==="string"){var e=g.numberRange.exec(c);if(e){var f=e[1],h=e[2],j="";for(var b=f;b<=h;b++)j+=",#"+d+"-"+b,k.push(b);i.filter(j.substring(1)).addClass("vg-highlight")}else a.find(".vg-line:contains("+c+")").each(function(){var a=$(this).addClass("vg-highlight");a.html(a.html().replace(c,''+c+""))}),k.push(c)}else{var l=d+"-"+this,m=i.filter("#"+l);m.length&&(m.addClass("vg-highlight"),k.push(c))}}}),!e&&f.set(d,k)}var a=$(this).addClass("vg-container").attr("id",||"vg-"+c++),,e=a.find("code"),i=!1,j=!1,k=[];e.length||(e=a,i=!0),h.source&&l&&e.text(l);var n=e.text();b.highlightBlock(e[0],;var o=e.html().split("\n"),p="",q="";if(!i){var s={},t=0;$.each(o,function(a,b){var c=a+h.firstLine,e=d+"-"+c,f=b;h.numbers&&(p+=''+c+"");if(s[t]){var i=g.multilineEnd.exec(b);i&&!i[1]?(f=''+f,delete s[t],t--):f=''+f+""}var j=g.multilineBegin.exec(b);j&&(t++,s[t]=j[1]),q+='




"+q),a.html(q),e=a.find("code"),a.find(".vg-number").click(function(b){var c=$(this),e=c.attr("rel"),h=a.find(e);if(h.hasClass("vg-highlight")){h.removeClass("vg-highlight"),k.splice(k.indexOf(c.text()),1),f.set(d,k),j=!1;return!1}var i=j;j=parseInt(g.pageNumber.exec(e)[1],10),b.shiftKey&&j?r(i<j?i+"-"+j:j+"-"+i,!0):r(j,b.ctrlKey?!1:!0);return!1});var u=a.find(".vg-gutter"),v=u.outerWidth(),w=0,x=!1;h.animateGutter&&a.scroll(function(a){if(this.scrollLeft!==w)if(this.scrollLeft>v){if(this.scrollLeft<w)w=this.scrollLeft,u.hide();else if(this.scrollLeft!==w){if(x)return;var b=this;w=this.scrollLeft,x=setTimeout(function(){x=!1;var a=b.scrollLeft;e.css("marginLeft",v),u.css({"float":"none",position:"absolute",left:a-v}).show().stop().animate({left:a})},500)}}else w=this.scrollLeft,clearTimeout(x),x=!1,u.css({"float":"",position:"",left:""}).show()})}else i&&a.addClass("vg-code");e.dblclick(function(){m(e[0]);return!1});if(h.maxLines>0){var y=a.find(".vg-line").height(),z=parseInt(e.css("paddingTop")),A=y*(h.maxLines+1)+z;a.css({minHeight:y+z,maxHeight:A})}h.highlight&&r(h.highlight,!0,!0);var B=f.get(d);B.length&&r(B,!1,!0)})}}function m(b){var c=a,d=a.document;if(d.body.createTextRange){var e=d.body.createTextRange();e.moveToElementText(b),}else if(d.createRange){var f=c.getSelection(),e=d.createRange();e.selectNodeContents(b),f.removeAllRanges(),f.addRange(e)}}var i={language:"auto",firstLine:1,maxLines:0,numbers:!0,highlight:null,animateGutter:!0,autoload:"",tab:" "};h=$.extend({},i,h);var j=this,k=0,l;n();return j}})(jQuery,this,typeof this.hljs!="undefined"?this.hljs:!1); /*! * Repo.js * @author Darcy Clarke * * Copyright (c) 2012 Darcy Clarke * Dual licensed under the MIT and GPL licenses. * */ (function($){ // Github repo $.fn.repo = function( options ){ // Context and Base64 methods var _this = this, keyStr64 = "ABCDEFGHIJKLMNOP" + "QRSTUVWXYZabcdef" + "ghijklmnopqrstuv" + "wxyz0123456789+/" + "=", encode64 = function(a){a=escape(a);var b="";var c,d,e="";var f,g,h,i="";var j=0;do{c=a.charCodeAt(j++);d=a.charCodeAt(j++);e=a.charCodeAt(j++);f=c>>2;g=(c&3)<<4|d>>4;h=(d&15)<<2|e>>6;i=e&63;if(isNaN(d)){h=i=64}else if(isNaN(e)){i=64}b=b+keyStr64.charAt(f)+keyStr64.charAt(g)+keyStr64.charAt(h)+keyStr64.charAt(i);c=d=e="";f=g=h=i=""}while(j<a.length);return b}, decode64 = function(a){var b="";var c,d,e="";var f,g,h,i="";var j=0;var k=/[^A-Za-z0-9\+\/\=]/g;if(k.exec(a)){}a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{f=keyStr64.indexOf(a.charAt(j++));g=keyStr64.indexOf(a.charAt(j++));h=keyStr64.indexOf(a.charAt(j++));i=keyStr64.indexOf(a.charAt(j++));c=f<<2|g>>4;d=(g&15)<<4|h>>2;e=(h&3)<<6|i;b=b+String.fromCharCode(c);if(h!=64){b=b+String.fromCharCode(d)}if(i!=64){b=b+String.fromCharCode(e)}c=d=e="";f=g=h=i=""}while(j<a.length);return unescape(b)}, transition = function(el, direction, init){ var opposite = (direction === 'left') ? '' : 'left'; height = el.outerHeight(true) + _this.container.find('h1').outerHeight(true) + parseInt(_this.container.css('padding-top')) + parseInt(_this.container.css('padding-bottom')); if(init){ el.addClass('active'); _this.container.css({'height' : height + 'px'}); } else { _this.container .find('') .css('position','absolute') .addClass(direction) .removeClass('active') .end() .css({'height' : height + 'px'}); el.addClass('active') .removeClass(opposite) .delay(250) .queue(function(){ $(this).css('position','relative').dequeue(); }); } }, getMimeTypeByExtension = function(extension){ var mimeTypes = { // images 'png': 'image/png', 'gif': 'image/gif', 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'ico': 'image/x-icon' }; return mimeTypes[extension] ? mimeTypes[extension] : 'text/plain'; }; // Settings _this.settings = $.extend({ user : '', name : '', branch : 'master', css : '@font-face{font-family:"Octicons Regular";src:url("");src:url("") format("embedded-opentype"),url("") format("woff"),url("") format("truetype"),url("") format("svg");font-weight:normal;font-style:normal}.repo,.repo *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.repo ul *{display:block;font-family:sans-serif;font-size:13px;line-height:18px}.repo{width:100%;margin:0 0 15px 0;position:relative;padding-bottom:1px;color:#555;overflow:hidden;height:300px;-webkit-transition:height .25s;-moz-transition:height .25s;-o-transition:height .25s;-ms-transition:height .25s;transition:height .25s}.repo .page{background:#f8f8f8;border:4px solid rgba(0,0,0,0.08);border-radius:3px;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);opacity:0;left:100%;width:98%;position:absolute;-webkit-transition:all .25s;-moz-transition:all .25s;-o-transition:all .25s;-ms-transition:all .25s;transition:all .25s}.repo{left:1%!important;-ms-filter:"alpha(opacity=100)";filter:alpha(opacity=100);opacity:1;display:block}.repo .page.left{left:-100%}.repo .loader{position:absolute;display:block;width:100%;height:300px;top:0;left:0;background:url( no-repeat center 50%}.repo.loaded .loader{display:none}.repo h1{padding:0 0 0 10px;font-family:sans-serif;font-size:20px;line-height:26px;color:#000;font-weight:normal}.repo h1 a:nth-of-type(1),.repo h1{font-weight:bold}.repo h1,.repo h1,.repo h1,.repo h1{color:#000}.repo h1 a,.repo h1 a:active,.repo h1 a:visited,.repo h1 a:hover{color:#4183c4;text-decoration:none}.repo h1 a:after{content:"/";color:#999;padding:0 5px;font-weight:normal}.repo h1 a:last-child:after{content:""}.repo .page,.repo ul{zoom:1}.repo .page:before,.repo .page:after,.repo ul:before,.repo ul:after{content:"";display:table}.repo .page:after,.repo ul:after{clear:both}.repo ul{border:1px solid rgba(0,0,0,0.25);margin:0;padding:0}.repo li{width:100%;margin:0;padding:0;float:left;border-bottom:1px solid #ccc;position:relative;white-space:nowrap}.repo li.titles{background:-webkit-linear-gradient(#fafafa,#eaeaea);background:-moz-linear-gradient(#fafafa,#eaeaea);background:-o-linear-gradient(#fafafa,#eaeaea);background:-ms-linear-gradient(#fafafa,#eaeaea);background:linear-gradient(#fafafa,#eaeaea);font-weight:bold;padding:10px 10px 8px 36px;text-shadow:0 1px 0 #fff}.repo li:before{content:" ";font-family:"Octicons Regular";position:absolute;top:10px;left:10px;font-size:18px;-webkit-font-smoothing:antialiased}.repo li.dir:before{content:" ";color:#80a6cd}.repo li.titles:before,.repo li.back:before{content:""}.repo li:last-child{border:0;padding-bottom:none;margin:0}.repo li a,.repo li a:visited,.repo li a:active{color:#4183c4;width:100%;padding:10px 10px 8px 36px;display:block;text-decoration:none}.repo li a:hover{text-decoration:underline}.repo li span{display:inline-block}.repo li span:nth-of-type(1){width:30%}.repo li span:nth-of-type(2){width:20%}.repo li span:nth-of-type(3){width:40%}.repo .vg-container{position:relative;overflow:auto;white-space:pre!important;word-wrap:normal!important}.repo .vg-container,.repo .vg-code{border:0;margin:0;overflow:auto}.repo .vg-code .vg-line,.repo .vg-gutter .vg-number{display:block;height:1.5em;line-height:1.5em!important}.repo .vg-gutter{float:left;min-width:20px;width:auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.repo .vg-number{cursor:pointer}.repo .vg-container{font-family:"Bitstream Vera Sans Mono","Courier New",monospace;font-size:13px;border:1px solid #ddd}.repo .vg-gutter{background-color:#ececec;border-right:1px solid #ddd;text-align:right;color:#aaa;padding:1em .5em;margin-right:.5em}.repo .vg-code *::-moz-selection,.repo .vg-code *::-webkit-selection,.repo .vg-code *::selection,.repo{background-color:#ffc}.repo .vg-line{color:blue;font-weight:bold;text-decoration:underline}.repo .vg-container .vg-code{display:block;padding:1em .5em;background:#fff}.repo .vg-code{color:#000;background:#f8f8ff;border:0;padding:.4em}.repo .vg-code .comment,.repo .vg-code .template_comment,.repo .vg-code .diff .header,.repo .vg-code .javadoc{color:#998;font-style:italic}.repo .vg-code .keyword,.repo .vg-code .css .rule .keyword,.repo .vg-code .winutils,.repo .vg-code .javascript .title,.repo .vg-code .lisp .title,.repo .vg-code .subst{color:#000;font-weight:bold}.vg-code .number,.vg-code .hexcolor{color:#40a070}.vg-code .string,.repo .vg-code .tag .value,.repo .vg-code .phpdoc,.repo .vg-code .tex .formula{color:#d14}.repo .vg-code .title,.repo .vg-code .id{color:#900;font-weight:bold}.repo .vg-code .javascript .title,.repo .vg-code .lisp .title,.repo .vg-code .subst{font-weight:normal}.repo .vg-code .class .title,.repo .vg-code .haskell .label,.repo .vg-code .tex .command{color:#458;font-weight:bold}.repo .vg-code .tag,.repo .vg-code .tag .title,.repo .vg-code .rules .property,.repo .vg-code .django .tag .keyword{color:#000080;font-weight:normal}.repo .vg-code .attribute,.repo .vg-code .variable,.repo .vg-code .instancevar,.repo .vg-code .lisp .body{color:#008080}.repo .vg-code .regexp{color:#009926}.repo .vg-code .class{color:#458;font-weight:bold}.repo .vg-code .symbol,.repo .vg-code .ruby .symbol .string,.repo .vg-code .ruby .symbol .keyword,.repo .vg-code .ruby .symbol .keymethods,.repo .vg-code .lisp .keyword,.repo .vg-code .tex .special,.repo .vg-code .input_number{color:#990073}.repo .vg-code .builtin,.repo .vg-code .built_in,.repo .vg-code .lisp .title{color:#0086b3}.repo .vg-code .codeprocessor,.repo .vg-code .pi,.repo .vg-code .doctype,.repo .vg-code .shebang,.repo .vg-code .cdata{color:#999;font-weight:bold}.repo .vg-code .deletion{background:#fdd}.repo .vg-code .addition{background:#dfd}.repo .vg-code .diff .change{background:#0086b3}.repo .vg-code .chunk{color:#aaa}.repo .vg-code .tex .formula{-ms-filter:"alpha(opacity=50)";filter:alpha(opacity=50);opacity:.5}.repo .image{padding:1em .5em;text-align:center}.repo .image .border-wrap{background-color:#fff;border:1px solid #999;line-height:0;display:inline-block}.repo .image img{border:1px solid #fff;background:url(}' }, options); // Extension Hashes _this.extensions = { as : 'actionscript', coffee : 'coffeescript', css : 'css', html : 'html', js : 'javascript', md : 'markdown', php : 'php', py : 'python', rb : 'ruby', }; // Repo _this.repo = { name : 'default', folders : [], files : [] }; // Namespace _this.namespace =; // Insert CSS if(typeof _this.settings.css != 'undefined' && _this.settings.css !== '' && $('#repojs_css').length <= 0) $('body').prepend($('

Up until about now I've been developing the Xenapi Admin Tools on my local cloud. I've been maintaining revisions on a local Subversion server which has been accessible by only the Xenapi Admin Project team. Now that we're slowly moving our projects public for inclusion in the Xen Cloud Platform's github I wanted to push Xenapi Admin Tools to github which is partly done as of today. 

The URL for the repo is Please feel free to browse the code and the development docs which outline the Xenapi Admin Tools spec and it's built in functions. I also have a yum repo file and a SPEC file for when I start creating rpms for Xen Cloud Platform/Xenserver. For now I would not consider that anything but alpha. At some point you'll be able to just install the Xenapi-admin-repo rpm and then yum install xenapi-admin-tools to install all of the tools including their manpages, config files and more. Currently a lot of these things don't exist. Also there are two branches of code in the github repo - 3.0 and 4.0. Not all tools are available in 4.0 yet as I'm still rewriting them. The difference is massive speedups with 4.0. Stay tuned for more news.

Installing from an XCP/Xenserver template usually gives you one Virtual Disk to install the operating system on. Depending on your needs this disk may not be large enough. Following is a tutorial on how to add an additional disk to a virtual machine.



Virtual Machine - A virtual machine is a computer that's virtualized and running on a hypervisor. In our case the hypervisor is Xen Cloud Platform/Xenserver. The Virtual Machine can be running any operating system.

Virtual Disk Image - Think of a Virtual Disk Image as a hard drive.

Storage Repository - A "box" storing Virtual Disk Images. Think of this as an external box storing virtual hard drives. The virtual hard drives are the Virtual Disk Images mentioned above.

Virtual Block Device - A Virtual Block Device connects a Virtual Disk Image to a Virtual Machine. In traditional computer terms you could think of it as the cable. 

The process for adding a hard drive to a real computer

  1. Insert the disk in the hard drive box
  2. Connect the cable to the hard drive box
  3. Insert the cable into the Computer

The process of adding a new Virtual Disk for a Virtual Machine is 

  1. Create a new Virtual Disk Image
  2. Create a new Virtual Block Device for it
  3. Connect the Virtual Block Device to the Virtual Machine


1. Get available free space

You will need to know how much free space is available on your Storage Repository.

[ root@cloud2 ~ ] xe sr-list
uuid ( RO)                : 36bf480a-5df9-4453-50f0-2bac4a86cb42
              name-label ( RW): localsr-cloud1
    name-description ( RW): 
                         host ( RO):
                        type ( RO): lvm
           content-type ( RO): user

Now that we have the Storage Repository's UUID number (36bf480a-5df9-4453-50f0-2bac4a86cb42) we can use xe sr-list again to give us the physical size and how much space is being utilized.

[ root@cloud2 ~ ] xe sr-list uuid=36bf480a-5df9-4453-50f0-2bac4a86cb42 \
physical-utilisation ( RO) : 214752559104 physical-size ( RO): 991600574464

Quick math (991600574464 - 214752559104 = 776848015360) shows us that we have about 776 MB free.

2. Create the Virtual Disk Image

Now that we know the available space on the storage repository we can make a new Virtual Disk Image using xe vdi-create.

[ root@cloud2 ~ ] xe vdi-create sr-uuid=bd1ac90d-7c23-dc07-dfa3-edc9f1cd73c4 \
name-label=DATADISK type=user virtual-size=100GiB

This command outputs the VDI's UUID. You can get information about any VDI using the xe vdi-list command.

[ root@cloud2 ~ ] xe vdi-list uuid=ee9c5daa-392c-4a0d-a5c1-4ebb7caabd73 
uuid ( RO)                : ee9c5daa-392c-4a0d-a5c1-4ebb7caabd73
          name-label ( RW): DATADISK
 name-description ( RW): 
                  sr-uuid ( RO): bd1ac90d-7c23-dc07-dfa3-edc9f1cd73c4
            virtual-size ( RO): 107374182400
               sharable ( RO): false
             read-only ( RO): false

The result of xe vm-list shows that the virtual size of the VDI is about 100 GB and it's name-label is DATADISK. To add this new disk to a VM I'll need to get the VM's UUID number by using xe vm-list.

[ root@cloud2 ~ ] xe vm-list name-label=CentOS6
     uuid ( RO)           : cefb9f88-0424-6701-5ba1-070490c69203
     name-label ( RW): CentOS6
      power-state ( RO): running


3. Get the available Virtual Block Device numbers

We will also need to know which Virtual Block Device numbers are available. We can use the xe vm-param-get command for this.

[ root@cloud2 ~ ] xe vm-param-get uuid=cefb9f88-0424-6701-5ba1-070490c69203 \ 
7; 8; 9; 10; 11; 12; 13; 14; 15

In summary:

  1. VDI UUID is ee9c5daa-392c-4a0d-a5c1-4ebb7caabd73
  2. VM UUID is cefb9f88-0424-6701-5ba1-070490c69203
  3. Available VBD numbers are 7, 8, 9, 10, 11, 12, 13, 14 and 15


4. Create the Virtual Block Device

Create the Virtual Block Device (VBD) using the xe vbd-create command and the VM UUID, VDI UUID and the first available VBD number.

[ root@cloud2 ~ ] xe vbd-create device=7 vm-uuid=cefb9f88-0424-6701-5ba1-070490c69203 \ 
vdi-uuid=ee9c5daa-392c-4a0d-a5c1-4ebb7caabd73 bootable=false mode=RW type=Disk

I created Virtual Block Device 7 (device=7). Using device=0 would have given me a /dev/dev/xvda which I already have. The xe-param-get command showed my first available Virtual Block Device number was 7. Notice that we associated the Virtual Disk Image (VDI) to the Virtual Machine (VM) by using a Virtual Block Device (VBD).

5. Plug in the disk to the VM

The VM won't see the disk yet as it hasn't been "plugged in". We can do this by either rebooting the VM or using the xe vbd-plug command. Let's plug the VBD into the running VM.

[ root@cloud2 ~ ]  xe vbd-plug uuid=333ab620-3ee1-0420-d31a-217e4ef1df45

6. Verify that it worked

Log into the VM via ssh or xenconsole and see if the disk appeared by catting /proc/partitions.

[root@Centos6 ~]# cat /proc/partitions
major minor  #blocks  name

 202        0    8388608 xvda
 202        1     102400 xvda1
 202        2    8285184 xvda2
 253        0    7733248 dm-0
 253        1     524288 dm-1
 202       16  104857600 xvdb

Page 2 of 9