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
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
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")])
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
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
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")])
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")])