diff --git a/nix/container.nix b/nix/container.nix index b6de2cc42..8c6047cb0 100644 --- a/nix/container.nix +++ b/nix/container.nix @@ -33,6 +33,7 @@ in boot.isContainer = true; + nixpkgs.system = mkIf (! any (platform: platform == builtins.currentSystem) platforms.linux) (mkOverride 999 "x86_64-linux"); }; } diff --git a/nixops/backends/container.py b/nixops/backends/container.py index 62431fbad..912aff803 100644 --- a/nixops/backends/container.py +++ b/nixops/backends/container.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from nixops.backends import MachineDefinition, MachineState +from nixops.nix_expr import py2nix import nixops.util import nixops.ssh_util import subprocess @@ -126,10 +127,14 @@ def create(self, defn, check, allow_reboot, allow_recreate): if self.vm_id is None: self.log("building initial configuration...") + eval_args = self.depl._eval_args(self.depl.nix_exprs) + eval_args['checkConfigurationOptions'] = False expr = " ".join([ '{ imports = [ ];', ' boot.isContainer = true;', ' networking.hostName = "{0}";'.format(self.name), + ' nixpkgs.system = let final = import {0};'.format(py2nix(eval_args, inline=True)), + ' in final.resources.machines.{0}.nixpkgs.system;'.format(self.name), ' users.extraUsers.root.openssh.authorizedKeys.keys = [ "{0}" ];'.format(self.client_public_key), '}']) diff --git a/nixops/deployment.py b/nixops/deployment.py index a76184b5b..28da1c2b1 100644 --- a/nixops/deployment.py +++ b/nixops/deployment.py @@ -250,16 +250,26 @@ def _nix_path_flags(self): flags.extend(["-I", "nixops=" + self.expr_path]) return flags + def _eval_args(self, exprs): + args = {key: RawValue(val) for key, val in self.args.iteritems()} + exprs_ = [RawValue(x) if x[0] == '<' else x for x in exprs] + eval_args = { + 'networkExprs' : exprs_, + 'args' : args, + 'uuid' : self.uuid, + 'deploymentName' : self.name if self.name else "" + } + return eval_args + def _eval_flags(self, exprs): flags = self._nix_path_flags() - args = {key: RawValue(val) for key, val in self.args.iteritems()} - exprs_ = [RawValue(x) if x[0] == '<' else x for x in exprs] + args = self._eval_args(exprs) flags.extend( - ["--arg", "networkExprs", py2nix(exprs_, inline=True), - "--arg", "args", py2nix(args, inline=True), - "--argstr", "uuid", self.uuid, - "--argstr", "deploymentName", self.name if self.name else "", + ["--arg", "networkExprs", py2nix(args['networkExprs'], inline=True), + "--arg", "args", py2nix(args['args'], inline=True), + "--argstr", "uuid", args['uuid'], + "--argstr", "deploymentName", args['deploymentName'], ""]) return flags @@ -592,34 +602,6 @@ def build_configs(self, include, exclude, dry_run=False, repair=False): names = map(lambda m: m.name, selected) - # If we're not running on Linux, then perform the build on the - # target machines. FIXME: Also enable this if we're on 32-bit - # and want to deploy to 64-bit. - if platform.system() != 'Linux' and os.environ.get('NIX_REMOTE') != 'daemon': - if os.environ.get('NIX_REMOTE_SYSTEMS') == None: - remote_machines = [] - for m in sorted(selected, key=lambda m: m.index): - key_file = m.get_ssh_private_key_file() - if not key_file: raise Exception("do not know private SSH key for machine ‘{0}’".format(m.name)) - # FIXME: Figure out the correct machine type of ‘m’ (it might not be x86_64-linux). - remote_machines.append("root@{0} {1} {2} 2 1\n".format(m.get_ssh_name(), 'i686-linux,x86_64-linux', key_file)) - # Use only a single machine for now (issue #103). - break - remote_machines_file = "{0}/nix.machines".format(self.tempdir) - with open(remote_machines_file, "w") as f: - f.write("".join(remote_machines)) - os.environ['NIX_REMOTE_SYSTEMS'] = remote_machines_file - else: - self.logger.log("using predefined remote systems file: {0}".format(os.environ['NIX_REMOTE_SYSTEMS'])) - - # FIXME: Use ‘--option use-build-hook true’ instead of setting - # $NIX_BUILD_HOOK, once Nix supports that. - os.environ['NIX_BUILD_HOOK'] = os.path.dirname(os.path.realpath(nixops.util.which("nix-build"))) + "/../libexec/nix/build-remote.pl" - - load_dir = "{0}/current-load".format(self.tempdir) - if not os.path.exists(load_dir): os.makedirs(load_dir, 0700) - os.environ['NIX_CURRENT_LOAD'] = load_dir - try: configs_path = subprocess.check_output( ["nix-build"] @@ -896,6 +878,32 @@ def worker(r): r.create(self.definitions[r.name], check=check, allow_reboot=allow_reboot, allow_recreate=allow_recreate) if is_machine(r): + # If we're not running on Linux, then perform the build on the + # target machines. FIXME: Also enable this if we're on 32-bit + # and want to deploy to 64-bit. + if platform.system() != 'Linux' and os.environ.get('NIX_REMOTE') != 'daemon': + if os.environ.get('NIX_REMOTE_SYSTEMS') == None: + # Use only a single machine for now (issue #103). + key_file = r.get_ssh_private_key_file() + if not key_file: raise Exception("do not know private SSH key for machine ‘{0}’".format(r.name)) + # FIXME: Figure out the correct machine type of ‘m’ (it might not be x86_64-linux). + remote_machine = "root@{0} {1} {2} 2 1\n".format(r.get_ssh_name(), 'i686-linux,x86_64-linux', key_file) + remote_machines_file = "{0}/nix.machines".format(self.tempdir) + with open(remote_machines_file, "w") as f: + f.write(remote_machine) + os.environ['NIX_REMOTE_SYSTEMS'] = remote_machines_file + + # FIXME: Use ‘--option use-build-hook true’ instead of setting + # $NIX_BUILD_HOOK, once Nix supports that. + os.environ['NIX_BUILD_HOOK'] = os.path.dirname(os.path.realpath(nixops.util.which("nix-build"))) + "/../libexec/nix/build-remote.pl" + + load_dir = "{0}/current-load".format(self.tempdir) + if not os.path.exists(load_dir): os.makedirs(load_dir, 0700) + os.environ['NIX_CURRENT_LOAD'] = load_dir + + else: + self.logger.log("using remote systems file: {0}".format(os.environ['NIX_REMOTE_SYSTEMS'])) + # The first time the machine is created, # record the state version. We get it from # /etc/os-release, rather than from the