{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8d0b9750-992b-44fa-a5e7-fb5e2951b969",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Bootstraping resource managers/orchestrators (k8s, swarm, openstack...)\n",
    "\n",
    "---\n",
    "\n",
    "- Website: https://discovery.gitlabpages.inria.fr/enoslib/index.html\n",
    "- Instant chat: https://framateam.org/enoslib\n",
    "- Source code: https://gitlab.inria.fr/discovery/enoslib\n",
    "\n",
    "---\n",
    "\n",
    "## Prerequisites\n",
    "\n",
    "<div class=\"alert alert-block alert-warning\">\n",
    "    <ul>\n",
    "    <li>⚠️ Make sure you've run the one time setup for your environment</li>\n",
    "    <li>⚠️ Make sure you're running this notebook under the right kernel</li>\n",
    "    </ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2349865a-8403-4181-a909-4ab39e884e00",
   "metadata": {},
   "outputs": [],
   "source": [
    "import enoslib as en\n",
    "\n",
    "en.check()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d2e6d5d2-0328-4070-9397-08e0fe6d1526",
   "metadata": {},
   "source": [
    "## Swarm / Death Star Bench\n",
    "\n",
    "[DeathStarBench](https://github.com/delimitrou/DeathStarBench) is a micro-service app built for benchmarking purpose (see [the academic paper](https://www.csl.cornell.edu/~delimitrou/papers/2019.asplos.microservices.pdf))\n",
    "\n",
    "One of its flavor comes packaged as a docker stack that you can deploy on a docker swarm.\n",
    "The purpose of the following is to show you how a docker swarm can be bootstraped using EnOSlib and how DeathStarBench can be deployed on Grid'5000.\n",
    "\n",
    "The spare some physical resources we first to go with virtual machines.\n",
    "\n",
    "### Get some resources"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23f903ed-defd-47d0-a326-3e99cddf232e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import enoslib as en\n",
    "\n",
    "# Enable rich logging\n",
    "_ = en.init_logging()\n",
    "\n",
    "\n",
    "# claim the resources\n",
    "conf = (\n",
    "    en.VMonG5kConf\n",
    "    .from_settings(job_name=\"enoslib_providers\")\n",
    "    .add_machine(\n",
    "        roles=[\"swarm\"],\n",
    "        cluster=\"paravance\",\n",
    "        number=10,\n",
    "        flavour=\"large\"\n",
    "    )\n",
    "    .finalize()\n",
    ")\n",
    "\n",
    "\n",
    "provider = en.VMonG5k(conf)\n",
    "\n",
    "roles, networks = provider.init()\n",
    "\n",
    "roles"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d8d084c5-7315-47c7-8ff4-82a0b8f30078",
   "metadata": {},
   "source": [
    "### Install some dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "33b40fb7-6ed2-4730-9198-959fe9131df3",
   "metadata": {},
   "outputs": [],
   "source": [
    "registry_opts = dict(type=\"external\", ip=\"docker-cache.grid5000.fr\", port=80)\n",
    "\n",
    "\n",
    "d = en.Docker(\n",
    "    agent=roles[\"swarm\"],\n",
    "    bind_var_docker=\"/tmp/docker\",\n",
    "    registry_opts=registry_opts,\n",
    "    swarm=True\n",
    ")\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "79b15cd2-e8dc-4ce5-9d32-7d9cb995dbaf",
   "metadata": {},
   "outputs": [],
   "source": [
    "d.deploy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c565ee47-de42-4cce-a135-fc486531ec24",
   "metadata": {},
   "outputs": [],
   "source": [
    "# install some of the deathstar's requirements\n",
    "with en.actions(roles=roles) as a:\n",
    "    a.pip(name=\"aiohttp\", state=\"present\")\n",
    "    a.apt(name=[\"libssl-dev\", \"libz-dev\", \"liblua5.2-dev\", \"luarocks\", \"git\"], state=\"present\", update_cache=True)\n",
    "    a.shell(\"luarocks install luasocket\")\n",
    "    a.git(repo=\"https://github.com/delimitrou/DeathStarBench.git\", dest=\"/tmp/dsb\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6617118-4608-47c0-935c-7401d726e183",
   "metadata": {},
   "source": [
    "### Start DeathStarBench"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad763041-7e47-49e6-a146-69b3b3cd16c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# start dsb\n",
    "r = en.run_command(\"docker stack deploy --compose-file=docker-compose-swarm.yml social\", roles=roles[\"swarm\"][0], chdir=\"/tmp/dsb/socialNetwork\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "239025fa-ed01-4fac-8f29-0e5141471365",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f\"\"\"\n",
    "Access the UI at {roles['swarm'][0].address}:8080\")\n",
    "---\n",
    "tip1: create a ssh port forwarding -> ssh -NL 8080:{roles['swarm'][0].address}:8080 access.grid5000.fr (and point your browser to http://localhost:8080)\n",
    "tip2: use a proxy socks -> ssh -ND 2100 access.grid5000.fr (and point your browser to http://{roles['swarm'][0].address}:8080)\n",
    "tip3: use the G5K vpn\n",
    "\"\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "03bfe07d-e570-461c-8e18-68270c6af5bc",
   "metadata": {},
   "outputs": [],
   "source": [
    "n.destroy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2761dab7-c903-4b65-9e0e-b6d7370a4f53",
   "metadata": {},
   "outputs": [],
   "source": [
    "# cleanup\n",
    "provider.destroy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c75a70a1-115b-4cda-ac25-7d982237626b",
   "metadata": {},
   "source": [
    "## K3S\n",
    "\n",
    "[K3s](https://k3s.io/) is a lightweight K8s distribution. For instance it's supposed to run on constrained hardware.\n",
    "\n",
    "For an (heavyweight) deployment of K8s, you can check [enos-kubernetes](https://gitlab.inria.fr/msimonin/enos-kubernetes/).\n",
    "\n",
    "### Get some resources"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a8b2326d-b7d9-4043-b5ba-ebbcc599b95d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import enoslib as en\n",
    "\n",
    "# Enable rich logging\n",
    "_ = en.init_logging()\n",
    "\n",
    "\n",
    "# claim the resources\n",
    "conf = (\n",
    "    en.VMonG5kConf\n",
    "    .from_settings(job_name=\"enoslib_providers\")\n",
    "    .add_machine(\n",
    "        roles=[\"master\"],\n",
    "        cluster=\"paravance\",\n",
    "        number=1,\n",
    "        flavour=\"large\"\n",
    "    )\n",
    "    .add_machine(\n",
    "        roles=[\"agent\"],\n",
    "        cluster=\"paravance\",\n",
    "        number=10,\n",
    "        flavour=\"large\"\n",
    "    )\n",
    "    .finalize()\n",
    ")\n",
    "\n",
    "\n",
    "provider = en.VMonG5k(conf)\n",
    "\n",
    "roles, networks = provider.init()\n",
    "\n",
    "roles"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cdedfe5f-252b-4290-9e45-65e8e8dde1aa",
   "metadata": {},
   "outputs": [],
   "source": [
    "# wait for the nodes\n",
    "en.wait_for(roles)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5c2ea1e7-517a-4460-847d-b8d7fca703a3",
   "metadata": {},
   "source": [
    "### Deploy K3s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bd47d6d9-be58-4a5d-a10a-89dd56e7a74a",
   "metadata": {},
   "outputs": [],
   "source": [
    "k3s = en.K3s(master=roles[\"master\"], agent=roles[\"agent\"])\n",
    "\n",
    "k3s.deploy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b1774f03-4322-4f44-95ab-69eef49585cc",
   "metadata": {},
   "source": [
    "**Accessing the dashboard**\n",
    "\n",
    "The dashboard should be reachable at http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/node?namespace=default\n",
    "see below for creating a tunnel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6480c507-a963-4bed-8c1a-010076916cd2",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Create a tunnel from your local machine to the head node:\")\n",
    "print(f\"ssh -NL 8001:{roles['master'][0].address}:8001 access.grid5000.fr\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27a5319a-467d-46b7-bca0-b2dd23cdc9d8",
   "metadata": {
    "tags": []
   },
   "source": [
    "### Cleanup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e75ff7a5-8c48-4052-acaa-b3afcfce0703",
   "metadata": {},
   "outputs": [],
   "source": [
    "provider.destroy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d6d132b-5553-4bbe-ac51-ab1270dbd9a8",
   "metadata": {},
   "source": [
    "## Openstack\n",
    "\n",
    "see [EnOS](https://github.com/BeyondTheClouds/enos)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9cdf58e-2eb7-4f03-b80b-a9e2a8f65659",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.2"
  },
  "toc-showcode": false,
  "toc-showmarkdowntxt": false
 },
 "nbformat": 4,
 "nbformat_minor": 5
}