NFS and LXC

Table of Contents
  1. Downloaded nfs_and_containers.cf). Place it in /var/cfengine/masterfiles/nfs_and_containers.cf.
  2. Run the following commands as root on the command line:

    
    

    The policy has some notes in reports for several of the bundles used in the bundle sequence. The information will also be shown as output when running the policy using cf-agent as described above.

Full Policy

body common control {

    inputs => {
       "/var/cfengine/masterfiles/lib/3.6/stdlib.cf",
    };

}

bundle common global_vars
{
    vars:

      "host_ip" string => "10.100.100.129";
      "lxc_network" string => "192.168.122";
      "gateway_ip" string => "$(lxc_network).1";
      "container_ip" string => "$(lxc_network).101";
      "container_name" string => "cfe-centos-2";

}

bundle agent remove_existing_items
{

  commands:
    "/usr/bin/lxc-stop -n $(globar_vars.container_name)";
    "/bin/rm -fr /root/3514296";
    "/bin/rm -fr /root/epel-release-6-8.noarch.rpm";
    "/bin/rm -fr /root/remi-release-6.rpm";
    "/bin/rm -fr /root/quick-install-cfengine-enterprise.sh";
    "/bin/rm -fr /var/lib/lxc/$(globar_vars.container_name)";
    "/bin/rm -fr /usr/share/lxc/templates/lxc-centos";

  reports:
    "This bundle ensures we are starting fresh. The command lines could be replaced by native CFEngine functionality.";

}

bundle agent change_service_state(service, state)
{

  commands:
    "/sbin/service $(service) $(state)";

}


bundle agent install_wget
{

  # Shouldn't be necessary, but just in case

  vars:

      "match_package" slist => {
        "wget"
      };

  packages:
      "$(match_package)"
      package_policy => "add",
      package_method => yum;

  reports:
    "Installing the wget package is done here using CFEngine's 'packages' promise type. The installation of wget may not be necessary in many cases, as it might already be installed.";

}

bundle agent get_cfe_script
{
  commands:
    "/usr/bin/wget -nc -P /root https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh";
}

bundle agent install_ssh_server_and_client
{

  vars:

      "match_package" slist => {
        "openssh-server",
        "openssh-clients"
      };

  packages:
      "$(match_package)"
      package_policy => "add",
      package_method => yum;

}

bundle agent install_lxc
{

  commands:
    "/usr/bin/wget -nc -P /root http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm";
    "/usr/bin/wget -nc -P /root http://rpms.famillecollet.com/enterprise/remi-release-6.rpm";
    "/bin/rpm -Uvh /root/remi-release-6*.rpm /root/epel-release-6*.rpm";

  vars:

      "match_package" slist => {
        "lxc"
      };

  packages:
      "$(match_package)"
      package_policy => "add",
      package_method => yum;

}

bundle agent install_git{

  vars:

      "match_package" slist => {
        "git"
      };

  packages:
      "$(match_package)"
      package_policy => "add",
      package_method => yum;

}

bundle agent get_lxc_centos_template
{

  commands:
    "/usr/bin/git clone https://gist.github.com/3514296.git /root/3514296";
    "/bin/cp /root/3514296/lxc-centos /usr/share/lxc/templates/"; #This could be done with CFEngine native functionality as well
    "/bin/chmod a+rx /usr/share/lxc/templates/lxc-centos";

  reports:
    "Clone, copy, and change the permissions on the centos template that lxc will use.";

}

bundle agent edit_lxc_centos_template
{
    files:

       "/usr/share/lxc/templates/lxc-centos"
       create    => "false",
       edit_line => replace_release_url;

  reports:
    "The release url probably needs modification, to change 10 to 11.1 (at the time of writing). This bundle makes the appropriate change, with some help from other bundles (replace_release_url and new_release_url).";

}


bundle edit_line replace_release_url
{
   replace_patterns:

   "RELEASE_URL=\"$MIRROR_URL/Packages/centos-release-$release-$releaseminor.el6.centos.10.$arch.rpm\".*"
      replace_with => new_release_url;
  reports:
    "Trying to find the current release url line";

}

body replace_with new_release_url
{
   replace_value => "RELEASE_URL=\"$MIRROR_URL/Packages/centos-release-$release-$releaseminor.el6.centos.11.1.$arch.rpm\"";
   occurrences => "all";

}

bundle agent create_centos_container
{

  commands:
    "/usr/bin/lxc-create -n $(global_vars.container_name) -t centos -- m 5";

  reports:
    "This bundle uses a command to create the container using the centos template that was downloaded earlier";

}



bundle agent configure_centos_container
{

  files:

    "/var/lib/lxc/$(global_vars.container_name)/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0"
       create    => "false",
       edit_line => modify_ifcfg;

    "/var/lib/lxc/$(global_vars.container_name)/rootfs/etc/sysconfig/network"
       create    => "false",
       edit_line => add_gateway_line;

    "/var/lib/lxc/$(global_vars.container_name)/rootfs/etc/resolv.conf"
       create    => "true",
       edit_line => add_nameserver;

  reports:
    "The default configuration of the container requires some modification to define a static IP address. This bundle modifies the appropriate files and also adds some information for DNS to resolv.conf.";

}

bundle edit_line modify_ifcfg
{
   replace_patterns:

   "BOOTPROTO=dhcp"
      replace_with => change_bootproto;

  insert_lines:
    "IPADDR=$(global_vars.container_ip)";
    "NETMASK=255.255.255.0";

}

body replace_with change_bootproto
{
   replace_value => "BOOTPROTO=static";
   occurrences => "all";
}

bundle edit_line add_gateway_line
{

  insert_lines:
    "GATEWAY=$(global_vars.gateway_ip)";

}

bundle edit_line add_nameserver
{

  insert_lines:
    "nameserver $(global_vars.gateway_ip)";

}

bundle agent start_centos_container
{

  commands:
    "/bin/rm /var/lib/lxc/cfe-centos-2/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0.cf-before-edit";
    "/usr/bin/lxc-start -d -n $(global_vars.container_name)";
  reports:
    "This bundle starts the container that was defined earlier, using a command.";

}

bundle agent install_nfs
{

  vars:

      "match_package" slist => {
        "nfs-utils"
      };

  packages:
      "$(match_package)"
      package_policy => "add",
      package_method => yum;

}

bundle agent configure_nfs
{

  files:

    "/var/lib/lxc/$(global_vars.container_name)/rootfs/etc/exports"
       create    => "true",
       edit_line => add_export_line;
    "/var/cfengine/masterfiles/def.cf"
      create => "false",
      edit_line => modify_def;

  reports:
    "NFS and CFEngine require some modifications to support the network bridge and container.";

}

bundle edit_line add_export_line
{

  insert_lines:
    "/home   $(global_vars.host_ip)(rw,sync,no_root_squash,no_subtree_check)";

}

bundle edit_line modify_def
{
   replace_patterns:

   "\"$(sys.policy_hub)/16\".*"
      replace_with => change_acl;

}

body replace_with change_acl
{
   replace_value => "\"$(sys.policy_hub)/16\",\"192.168.122.*\",";
   occurrences => "all";
}




bundle agent start_nfs
{

  methods:

      "any" usebundle => change_service_state("rpcbind","restart");
      "any" usebundle => change_service_state("nfs","restart");
      "any" usebundle => change_service_state("nfslock","restart");

  reports:
    "This bundle starts NFS and related services. It uses restart rather than start just in case the services were already running and modifications made earlier need to be recognized.";

}

bundle agent setup_ssh_connection_to_container
{

  commands:

    "/usr/bin/sshpass -p \"password\" /usr/bin/ssh -o StrictHostKeyChecking=no root@$(global_vars.container_ip) /usr/bin/yum -y install openssh-server openssh-clients";
    "/usr/bin/sshpass -p \"password\" /usr/bin/ssh-copy-id -i /root/.ssh/id_rsa.pub root@$(global_vars.container_ip)";

  reports:
    "Setting up an ssh connection to the container will be used to pass commands from the host machine.";

}

bundle agent setup_nfs_on_container
{

  commands:
    "/usr/bin/ssh $(global_vars.container_ip) /usr/bin/yum -y install nfs-utils";
  reports:
    "NFS needs to be installed onto the container. This bundle does this using a command call to ssh, and in turn to the yum installer on the container.";

}

bundle agent mount_shared_folder_on_container
{

  commands:
    "/usr/bin/ssh $(global_vars.container_ip) /bin/mount $(global_vars.container_ip):/root /root/mount";
  reports:
    "After NFS is installed on the container, the shared directory between the two machines can be mounted.";

}

bundle agent install_cfengine_on_container
{

  commands:
    "/usr/bin/ssh $(global_vars.container_ip) /bin/chmod a+x /root/mount/quick-install-cfengine-cfengine-enterprise.sh";
    "/usr/bin/ssh $(global_vars.container_ip) /root/mount/quick-install-cfengine-cfengine-enterprise.sh agent";
   reports:
    "After the shared folder is mounted, a call to the CFEngine script install can be made from the host via ssh to the container";

}

bundle agent bootstrap_cfengine_on_container
{

  commands:
    "/usr/bin/ssh $(global_vars.container_ip) /var/cfengine/bin/cf-agent --bootstrap $(global_vars.gateway_ip)";

  reports:
   "CFEngine should now be installed, and this bundle will boostrap it to the host machine that is running hub.";
  "Note: changes may need to be made to /var/cfengine/masterfiles/controls/cf_serverd.cf on the hub to properly use the container as a CFEngine host across a network bridge (in this tutorial via the 192.168.122.1 gateway). Look for the section '!am_policy_hub.enterprise::' and change all three lines that state 'admit => { \"$(sys.policy_hub)\"};' to read 'admit => { \"$(sys.policy_hub)\",\"192.168.122.1\" };'.";

}