Exemple #1
0
def stop_controllers(args):
    if args.mode not in ["all", "appcontroller"]:
        logging.error(
            "Unknown stop mode {}, expected one of ['all', 'appcontroller']".
            format(args.mode))
        return 1

    if args.mode == "appcontroller":
        if args.package is not None:
            logging.error(
                "Package argument is only meaningful on server controllers")
            return 1
        with util.FLock(open(os.path.join(dataroot, "controllers.json"),
                             "r+")) as f:
            try:
                d = json.load(f)
                for c in d["controllers"]:
                    for pid in [
                            p["pid"] for p in d["controllers"][c]["procs"]
                    ]:
                        try:
                            # TODO: gentler (controller specific) way of shutting down?
                            os.kill(pid, signal.SIGTERM)
                            logging.info(
                                "Sent a SIGTERM to process {} for controller {}"
                                .format(pid, c))
                            time.sleep(5)
                            os.kill(pid, signal.SIGKILL)
                            logging.info(
                                "Sent a SIGKILL to process {} for controller {}"
                                .format(pid, c))
                        except ProcessLookupError:
                            pass
                f.seek(0)
                f.truncate()
                del d["controllers"]
                json.dump(d, f)
            except KeyError:
                logging.info("Nothing to stop")
            except Exception as err:
                logging.error(err)
                return 1
    else:
        if args.package is None:
            logging.error(
                "Need a package to stop (for client host names, ports, ...)")
            return 1
        with util.TempDir("netide-stop") as t:
            pkg = Package(args.package, t)
            for c in pkg.get_clients():
                ssh = util.build_ssh_commands(c)
                logging.debug("SSH {}".format(ssh))

                cmd = "cd ~/netide-loader; ./netideloader.py stop --mode=appcontroller"
                util.spawn_logged(ssh + [cmd])
    return 0
Exemple #2
0
def stop_controllers(args):
    if args.mode not in ["all", "appcontroller"]:
        logging.error("Unknown stop mode {}, expected one of ['all', 'appcontroller']".format(args.mode))
        return 1

    if args.mode == "appcontroller":
        if args.package is not None:
            logging.error("Package argument is only meaningful on server controllers")
            return 1
        with util.FLock(open(os.path.join(dataroot, "controllers.json"), "r+")) as f:
            try:
                d = json.load(f)
                for c in d["controllers"]:
                    for pid in [p["pid"] for p in d["controllers"][c]["procs"]]:
                        try:
                            # TODO: gentler (controller specific) way of shutting down?
                            os.kill(pid, signal.SIGTERM)
                            logging.info("Sent a SIGTERM to process {} for controller {}".format(pid, c))
                            time.sleep(5)
                            os.kill(pid, signal.SIGKILL)
                            logging.info("Sent a SIGKILL to process {} for controller {}".format(pid, c))
                        except ProcessLookupError:
                            pass
                f.seek(0)
                f.truncate()
                del d["controllers"]
                json.dump(d, f)
            except KeyError:
                logging.info("Nothing to stop")
            except Exception as err:
                logging.error(err)
                return 1
    else:
        if args.package is None:
            logging.error("Need a package to stop (for client host names, ports, ...)")
            return 1
        with util.TempDir("netide-stop") as t:
            pkg = Package(args.package, t)
            for c in pkg.get_clients():
                ssh = util.build_ssh_commands(c)
                logging.debug("SSH {}".format(ssh))

                cmd = "cd ~/netide-loader; ./netideloader.py stop --mode=appcontroller"
                util.spawn_logged(ssh + [cmd])
    return 0
Exemple #3
0
def do_client_installs(pkgpath, dataroot):
    "Dispatches installation requests to client machines after gaining a foothold on them. Requires passwordless SSH access to \
    client machines and passwordless root via sudo on client machines"

    with util.TempDir("netide-client-installs") as t:
        pkg = Package(pkgpath, t)
        if not pkg.load_apps_and_controller():
            logging.error("There's something wrong with the package")
            return 2
        clients = pkg.get_clients()
        #controller = pkg.controllers
        #print("controller: ")
        #print(controller)
        #for n in controller:
        #    print("instance of controller: ")
        #    print(n)
        #    for i in controller[n]:
        #        print(i)

        util.editPlaybookClient(pkg)
        util.spawn_logged(["ansibleEnvironment/bin/ansible-playbook", "-v", os.path.join("Playbook_Setup", "siteClient.yml")])
Exemple #4
0
def load_package(args):
    if args.mode == "appcontroller":
        p = Package(args.package, dataroot)
        if not p.applies():
            logging.error("There's something wrong with the package")
            return 2

        os.makedirs(dataroot, exist_ok=True)
        dp = os.path.join(dataroot, "controllers.json")

        with util.FLock(open(dp, "r"), shared=True) as f:
            try:
                data = json.load(f)
            except ValueError:
                data = {}
            if data.get("cksum", "") != p.cksum:
                logging.debug("{} != {}".format(data.get("cksum", ""),
                                                p.cksum))
                logging.error(
                    "Package changed since installation. Re-run `install' with this package."
                )
                # XXX
                # return 1
        try:
            pids = p.start(data.get("controllers", {}))
            logging.info(pids)
            data["controllers"] = pids
            with util.FLock(open(dp, "w")) as f:
                json.dump(data, f, indent=2)
        except Exception as err:
            logging.error(err)
            return 1
    else:
        # TODO:
        # [X] Start server controller (if not already running)
        # [ ] Make sure NetIDE stuff is running in server controller
        # [X] Start NetIDE core (if not already running)
        # [X] Connect to application controllers:
        #   [X] Copy package to remote machine
        #   [X] Run `load' with --mode=appcontroller
        # [ ] Ping core about new composition

        with util.TempDir("netide-client-dispatch") as t:
            pkg = Package(args.package, t)
            util.write_ansible_hosts(pkg.get_clients(),
                                     os.path.join(t, "ansible-hosts"))

            vars = {
                "netide_karaf_bin":
                "{{ansible_user_dir}}/karaf/apache-karaf-4.0.0/assemblies/apache-karaf/target/assembly/bin"
            }
            tasks = []
            tasks.append({
                "name": "checking if Karaf (for NetIDE core) is running",
                "shell": "bash ./client -r 2 logout",
                "args": {
                    "chdir": "{{netide_karaf_bin}}"
                },
                "ignore_errors": True,
                "register": "karaf_running"
            })
            tasks.append({
                "name": "launching karaf (for NetIDE core)",
                "shell": "bash ./start",
                "args": {
                    "chdir": "{{netide_karaf_bin}}"
                },
                "when": "karaf_running.rc != 0"
            })

            ctasks = []
            ctasks.append({"shell": "mktemp -d", "register": "tmpdir"})
            src = os.path.join(os.getcwd(), args.package)
            ctasks.append({"copy": {"dest": "{{tmpdir.stdout}}", "src": src}})

            ctasks.append({
                "name":
                "loading package",
                "shell":
                "nohup ./netideloader.py load --mode=appcontroller {{tmpdir.stdout}}/"
                + str(args.package),
                "args": {
                    "chdir": "~/netide-loader"
                }
            })

            playbook = [{
                "hosts": "localhost",
                "tasks": tasks,
                "vars": vars
            }, {
                "hosts": "clients",
                "tasks": ctasks
            }]
            with open(os.path.join(t, "a-playbook.yml"), "w") as ah:
                json.dump(playbook, ah, indent=2)
            util.spawn_logged([
                "ansible-playbook", "-i",
                os.path.join(t, "ansible-hosts"),
                os.path.join(t, "a-playbook.yml")
            ])

            # Make netip python library available. This has been installed here by installer.do_server_install()
            p = ["~", "Core", "libraries", "netip", "python"]
            sys.path.append(os.path.expanduser(os.path.join(*p)))
            from netip import NetIDEOps

            m = NetIDEOps.netIDE_encode(
                NetIDEOps.NetIDE_type["NETIDE_MGMT"], None, None, None,
                json.dumps({
                    "command": "update_composition",
                    "parameters": {
                        "composition": pkg.get_composition()
                    }
                }).encode())

            with zmq.Context() as ctx, ctx.socket(zmq.REQ) as s:
                s.connect("tcp://localhost:5555")
                s.send(m)
    return 0
Exemple #5
0
def load_package(args):
    if args.mode == "appcontroller":
        p = Package(args.package, dataroot)
        if not p.applies():
            logging.error("There's something wrong with the package")
            return 2

        os.makedirs(dataroot, exist_ok=True)
        dp = os.path.join(dataroot, "controllers.json")

        with util.FLock(open(dp, "r"), shared=True) as f:
            try:
                data  = json.load(f)
            except ValueError:
                data = {}
            if data.get("cksum", "") != p.cksum:
                logging.debug("{} != {}".format(data.get("cksum", ""), p.cksum))
                logging.error("Package changed since installation. Re-run `install' with this package.")
                # XXX
                # return 1
        try:
            pids = p.start(data.get("controllers", {}))
            logging.info(pids)
            data["controllers"] = pids
            with util.FLock(open(dp, "w")) as f:
                json.dump(data, f, indent=2)
        except Exception as err:
            logging.error(err)
            return 1
    else:
        # TODO:
        # [X] Start server controller (if not already running)
        # [ ] Make sure NetIDE stuff is running in server controller
        # [X] Start NetIDE core (if not already running)
        # [X] Connect to application controllers:
        #   [X] Copy package to remote machine
        #   [X] Run `load' with --mode=appcontroller
        # [ ] Ping core about new composition

        with util.TempDir("netide-client-dispatch") as t:
            pkg = Package(args.package, t)
            util.write_ansible_hosts(pkg.get_clients(), os.path.join(t, "ansible-hosts"))

            vars = {"netide_karaf_bin":
                    "{{ansible_user_dir}}/karaf/apache-karaf-4.0.0/assemblies/apache-karaf/target/assembly/bin"}
            tasks = []
            tasks.append({
                "name": "checking if Karaf (for NetIDE core) is running",
                "shell": "bash ./client -r 2 logout",
                "args": {"chdir": "{{netide_karaf_bin}}"},
                "ignore_errors": True,
                "register": "karaf_running"})
            tasks.append({
                "name": "launching karaf (for NetIDE core)",
                "shell": "bash ./start",
                "args": {"chdir": "{{netide_karaf_bin}}"},
                "when": "karaf_running.rc != 0"})

            ctasks = []
            ctasks.append({
                "shell": "mktemp -d",
                "register": "tmpdir"})
            src = os.path.join(os.getcwd(), args.package)
            ctasks.append({
                "copy": {
                    "dest": "{{tmpdir.stdout}}",
                    "src": src}})

            ctasks.append({
                "name": "loading package",
                "shell": "nohup ./netideloader.py load --mode=appcontroller {{tmpdir.stdout}}/" + str(args.package),
                "args": {"chdir": "~/netide-loader"}})

            playbook = [{"hosts": "localhost", "tasks": tasks, "vars": vars}, {"hosts": "clients", "tasks": ctasks}]
            with open(os.path.join(t, "a-playbook.yml"), "w") as ah:
                json.dump(playbook, ah, indent=2)
            util.spawn_logged(["ansible-playbook", "-i", os.path.join(t, "ansible-hosts"), os.path.join(t, "a-playbook.yml")])

            # Make netip python library available. This has been installed here by installer.do_server_install()
            p = ["~", "Core", "libraries", "netip", "python"]
            sys.path.append(os.path.expanduser(os.path.join(*p)))
            from netip import NetIDEOps

            m = NetIDEOps.netIDE_encode(
                    NetIDEOps.NetIDE_type["NETIDE_MGMT"],
                    None,
                    None,
                    None,
                    json.dumps({"command": "update_composition", "parameters": {"composition": pkg.get_composition()}}).encode())

            with zmq.Context() as ctx, ctx.socket(zmq.REQ) as s:
                s.connect("tcp://localhost:5555")
                s.send(m)
    return 0
Exemple #6
0
def do_server_install(pkg):
    logging.debug("Doing server install for '{}' now".format(pkg))

    prefix = os.path.expanduser("~")

    with util.TempDir("netide-server-install") as t:
        p = Package(pkg, t)
        if "server" not in p.config:
            raise InstallException('"server" section missing from configuration!')

        conf = p.config["server"]
        if "host" in conf and platform.node() != conf["host"]:
            raise InstallException("Attempted server installation on host {} (!= {})".format(platform.node(), conf["host"]))

        tasks = []

        tasks.append({
            "name": "Clone NetIDE Engine (master)",
            "git": {
                "repo": "https://github.com/fp7-netide/Engine.git",
                "dest": "{{ansible_user_dir}}/Engine"}})
        tasks.append({
            "name": "Clone NetIDE Engine (Core)",
            "git": {
                "repo": "https://github.com/fp7-netide/Engine.git",
                "dest": "{{ansible_user_dir}}/Core",
                "version": "CoreImplementation"}})
        tasks.append({
            "name": "Clone NetIDE IDE",
            "git": {
                "repo": "https://github.com/fp7-netide/IDE.git",
                "dest": "{{ansible_user_dir}}/IDE",
                "version": "development"}})

        tasks.append({
            "name": "Build NetIDE netip library (java)",
            "shell": "mvn install -Dskiptests",
            "args": {
                "chdir": "{{ansible_user_dir}}/Engine/libraries/netip/java",
                "creates": "{{ansible_user_dir}}/Engine/libraries/netip/java/target/netip-1.0.0.0.jar"}})
        tasks.append({
            "name": "Build NetIDE Core",
            "shell": "mvn install -DskipTests",
            "args": {
                "chdir": "{{ansible_user_dir}}/Core/core",
                "creates": "{{ansible_user_dir}}/Core/core/core.caos/target/core.caos-1.0.0.0.jar"}})

        tasks.append({"file": {"path": "{{ansible_user_dir}}/karaf", "state": "directory"}})
        tasks.append({
            "name": "Downloading Karaf",
            "unarchive": {
                "copy": "no",
                "creates": "{{ansible_user_dir}}/karaf/apache-karaf-4.0.0",
                "dest": "{{ansible_user_dir}}/karaf",
                "src": "http://apache.lauf-forum.at/karaf/4.0.0/apache-karaf-4.0.0-src.tar.gz"}})
        tasks.append({
            "name": "Building and installing Karaf",
            "shell": "mvn -Pfastinstall",
            "args": {
                "chdir": "{{ansible_user_dir}}/karaf/apache-karaf-4.0.0",
                "creates": "{{netide_karaf_assembly}}/bin"}})
        # This avoids conflicts with ODL's Karaf instance
        tasks.append({
            "name": "Reconfiguring Karaf RMI ports (1/2)",
            "lineinfile": {
                "dest": "{{netide_karaf_assembly}}/etc/org.apache.karaf.management.cfg",
                "regexp": "^rmiRegistryPort.*1099",
                "line": "rmiRegistryPort = 1100"}})
        tasks.append({
            "name": "Reconfiguring Karaf RMI ports (2/2)",
            "lineinfile": {
                "dest": "{{netide_karaf_assembly}}/etc/org.apache.karaf.management.cfg",
                "regexp": "^rmiServerPort.*44444",
                "line": "rmiServerPort = 55555"}})
        tasks.append({ "file": {"path": "{{netide_karaf_assembly}}/bin/karaf", "mode": "ugo+rx"}})
        tasks.append({ "file": {"path": "{{netide_karaf_assembly}}/bin/start", "mode": "ugo+rx"}})
        tasks.append({ "file": {"path": "{{netide_karaf_assembly}}/bin/client", "mode": "ugo+rx"}})
        tasks.append({
            "name": "Checking of Karaf is running",
            "shell": "bash ./client -r 2 logout",
            "args": {"chdir": "{{netide_karaf_assembly}}/bin"},
            "ignore_errors": True,
            "register": "karaf_running"})
        tasks.append({
            "name": "Starting Karaf",
            "shell": "bash ./start",
            "when": "karaf_running.rc != 0",
            "args": { "chdir": "{{netide_karaf_assembly}}/bin" }})
        tasks.append({
            "name": "Adding NetIDE Maven Repo to Karaf",
            "shell": 'bash ./client -r 10 "feature:repo-add mvn:eu.netide.core/core/1.0.0.0/xml/features"',
            "args": { "chdir": "{{netide_karaf_assembly}}/bin" }})
        tasks.append({
            "name": "Installing NetIDE Core Karaf feature",
            "shell": 'bash ./client -r 10 "feature:install netide-core"',
            "args": { "chdir": "{{netide_karaf_assembly}}/bin"}})

        tasks.append({
            "name": "Installing NetIDE Engine",
            "shell": "bash {{netide_scripts}}/install_engine.sh"})

        if conf["type"] not in ["odl"]:
            raise InstallException("Don't know how to do a server controller installation for controller {}!".format(conf["type"]))
        tasks.append({
            "name": "Installing {}".format(conf["type"]),
            "shell": "bash {{netide_scripts}}/install_{}.sh".format(conf["type"])})

        with open(os.path.join(t, "a-playbook.yml"), "w") as fh:
            json.dump([{
                "hosts": "localhost",
                "tasks": tasks,
                "vars": {
                    "netide_karaf_assembly":
                        "{{ansible_user_dir}}/karaf/apache-karaf-4.0.0/assemblies/apache-karaf/target/assembly",
                    "netide_scripts": "{{ansible_user_dir}}/IDE/plugins/eu.netide.configuration.launcher/scripts" }}], fh)
        util.write_ansible_hosts([], os.path.join(t, "a-hosts"))
        util.spawn_logged(["ansible-playbook", "-i", os.path.join(t, "a-hosts"), os.path.join(t, "a-playbook.yml")])
Exemple #7
0
def do_client_installs(pkgpath, dataroot):
    "Dispatches installation requests to client machines after gaining a foothold on them. Requires passwordless SSH access to \
    client machines and passwordless root via sudo on client machines"

    with util.TempDir("netide-client-installs") as t:
        pkg = Package(pkgpath, t)
        clients = pkg.get_clients()

        util.write_ansible_hosts(clients, os.path.join(t, "ansible-hosts"))

        # Install Python2.7 so we can use ansible
        # XXX: make the package name configurable
        util.spawn_logged(["ansible", "clients", "-i", os.path.join(t, "ansible-hosts"),
            "-m", "raw", "-a", install_package_command.format("python2.7")])

        tasks = []

        # Can't use `synchronize' here because that doesn't play nice with ssh options
        tasks.append({
            "name": "Copy NetIDE loader",
            "copy": {
                "dest": '{{ansible_user_dir}}/netide-loader-tmp',
                "src" : os.getcwd()}})

        # We need to do this dance because `copy' copies to a subdir unless
        # `src' ends with a '/', in which case it doesn't work at all (tries
        # to write to '/' instead)
        tasks.append({
            "shell": "mv {{ansible_user_dir}}/netide-loader-tmp/loader {{ansible_user_dir}}/netide-loader",
            "args": {"creates": "{{ansible_user_dir}}/netide-loader"}})
        tasks.append({"file": {"path": "{{ansible_user_dir}}/netide-loader-tmp", "state": "absent"}})
        tasks.append({"file": {"path": "{{ansible_user_dir}}/netide-loader/netideloader.py", "mode": "ugo+rx"}})

        tasks.append({
            "name": "Bootstrap NetIDE loader",
            "shell": "bash ./setup.sh",
            "args": { "chdir": "{{ansible_user_dir}}/netide-loader" }})

        tasks.append({
            "name": "Clone IDE repository",
            "git": {
                "repo": "http://github.com/fp7-netide/IDE.git",
                "dest": "{{ansible_user_dir}}/IDE",
                "version": "development"}})

        tasks.append({
            "name": "Install Engine",
            "shell": "bash {{ansible_user_dir}}/IDE/plugins/eu.netide.configuration.launcher/scripts/install_engine.sh"})

        tasks.append({
            "file": {
                "path": dataroot,
                "state": "directory"}})

        tasks.append({
            "name": "Register Package checksum",
            "copy": {
                "content": json.dumps({"cksum": pkg.cksum}, indent=2),
                "dest": os.path.join(dataroot, "controllers.json")}})

        playbook = [{"hosts": "clients", "tasks": tasks}]

        for c in clients:
            ctasks = []

            apps = []
            # Collect controllers per client machine and collect applications
            for con in pkg.controllers_for_node(c[0]):
                apps.extend(con.applications)
                cname = con.__name__.lower()
                if cname not in ["ryu", "floodlight", "odl", "pox", "pyretic"]:
                    raise InstallException("Don't know how to install controller {}".format(cname))

                script = ["{{ansible_user_dir}}", "IDE", "plugins", "eu.netide.configuration.launcher", "scripts"]
                script.append("install_{}.sh".format(cname))

                ctasks.append({
                    "name": "install controller {}".format(cname),
                    "shell": "bash {}".format(os.path.join(*script)),
                    "args": {"chdir": "{{ansible_user_dir}}"}})

            # Install application dependencies
            # XXX: ugly :/
            # XXX: libraries
            for a in apps:
                reqs = a.metadata.get("requirements", {}).get("Software", {})

                # Languages
                for l in reqs.get("Languages", {}):
                    if l["name"] == "python":
                        if l["version"].startswith("3"):
                            l["name"] += "3"
                        else:
                            l["name"] += "2"
                    elif l["name"] == "java":
                        if "7" in l["version"]:
                            l["name"] = "openjdk-7-jdk"
                        elif "8" in l["version"]:
                            l["name"] = "openjdk-8-jdk"
                        else:
                            l["name"] = "openjdk-6-jdk"

                    ctasks.append({
                        "name": "install {} (for app {})".format(l["name"], str(a)),
                        "apt": {"pkg": "{}={}*".format(l["name"], l["version"])}})
            playbook.append({"hosts": c[0], "tasks": ctasks})

        # A valid JSON-document is also valid YAML, so we can take a small shortcut here
        with open(os.path.join(t, "a-playbook.yml"), "w") as ah:
            json.dump(playbook, ah, indent=2)
        util.spawn_logged(["ansible-playbook", "-i", os.path.join(t, "ansible-hosts"), os.path.join(t, "a-playbook.yml")])