Branch: refs/heads/master
  Home:   https://github.com/NixOS/charon
  Commit: 9f8e8da93f8d0fc821440fc703480404d0552384
      
https://github.com/NixOS/charon/commit/9f8e8da93f8d0fc821440fc703480404d0552384
  Author: Eelco Dolstra <eelco.dols...@logicblox.com>
  Date:   2012-04-24 (Tue, 24 Apr 2012)

  Changed paths:
    M charon/backends/ec2.py
    M nix/options.nix

  Log Message:
  -----------
  Add support for elastic IP addresses

You can associate an elastic IP address with a machine by saying

  deployment.ec2.elasticIPv4 = "54.247.165.166";

If the value of this option changes, Charon will automatically
associate or disassociate as required.

Fixes #3.


diff --git a/charon/backends/ec2.py b/charon/backends/ec2.py
index bfaed0c..1e144ba 100644
--- a/charon/backends/ec2.py
+++ b/charon/backends/ec2.py
@@ -38,6 +38,7 @@ def f(xml):
                     'fsType': 
xml.find("attrs/attr[@name='fsType']/string").get("value"),
                     'deleteOnTermination': 
xml.find("attrs/attr[@name='deleteOnTermination']/bool").get("value") == "true"}
         self.block_device_mapping = {_xvd_to_sd(k.get("name")): f(k) for k in 
x.findall("attr[@name='blockDeviceMapping']/attrs/attr")}
+        self.elastic_ipv4 = 
x.find("attr[@name='elasticIPv4']/string").get("value")
 
     def make_state():
         return MachineState()
@@ -68,6 +69,7 @@ def _reset_state(self):
         self._instance_id = None
         self._public_ipv4 = None
         self._private_ipv4 = None
+        self._elastic_ipv4 = None
         self._tags = {}
         self._block_device_mapping = {}
         self._public_host_key = False
@@ -95,6 +97,7 @@ def serialise(self):
         if self._public_host_key: y['publicHostKey'] = self._public_host_key
         if self._public_vpn_key: y['publicVpnKey'] = self._public_vpn_key
         if self._root_device_type: y['rootDeviceType'] = self._root_device_type
+        if self._elastic_ipv4: y['elasticIPv4'] = self._elastic_ipv4
         x['ec2'] = y
         
         return x
@@ -121,10 +124,12 @@ def deserialise(self, x):
         self._vpn_key_set = y.get('vpnKeySet', False)
         self._public_vpn_key = y.get('publicVpnKey', None)
         self._root_device_type = y.get('rootDeviceType', None)
+        self._elastic_ipv4 = y.get('elasticIPv4', None)
 
         
     def get_ssh_name(self):
-        assert self._public_ipv4
+        if not self._public_ipv4:
+            raise Exception("EC2 machine ‘{0}’ does not have a public IPv4 
address (yet)".format(self.name))
         return self._public_ipv4
 
     def get_physical_spec(self, machines):
@@ -339,15 +344,34 @@ def create(self, defn, check):
             self._tags = tags
             self.write()
 
+        # Assign or release an elastic IP address, if given.
+        if (self._elastic_ipv4 or "") != defn.elastic_ipv4:
+            self.connect()
+            if defn.elastic_ipv4 != "":
+                print >> sys.stderr, "associating IP address ‘{0}’ with EC2 
machine ‘{1}’...".format(
+                    defn.elastic_ipv4, self.name)
+                self._conn.associate_address(instance_id=self._instance_id, 
public_ip=defn.elastic_ipv4)
+                self._elastic_ipv4 = defn.elastic_ipv4
+                self._public_ipv4 = defn.elastic_ipv4
+                self._ssh_pinged = False
+                charon.known_hosts.add(defn.elastic_ipv4, 
self._public_host_key)
+            else:
+                print >> sys.stderr, "disassociating IP address ‘{0}’ from EC2 
machine ‘{1}’...".format(
+                    self._elastic_ipv4, self.name)
+                self._conn.disassociate_address(public_ip=self._elastic_ipv4)
+                self._elastic_ipv4 = None
+                self._public_ipv4 = None
+            self.write()
+
         # Wait for the IP address.
-        if not self._private_ipv4 or check:
+        if not self._public_ipv4 or check:
             instance = self._get_instance_by_id(self._instance_id)
             sys.stderr.write("waiting for IP address of ‘{0}’... 
".format(self.name))
             while True:
                 sys.stderr.write("[{0}] ".format(instance.state))
                 if instance.state not in {"pending", "running", "scheduling", 
"launching"}:
                     raise Exception("EC2 instance ‘{0}’ failed to start (state 
is ‘{1}’)".format(self._instance_id, instance.state))
-                if instance.private_ip_address: break
+                if instance.ip_address: break
                 time.sleep(3)
                 instance.update()
             sys.stderr.write("{0} / {1}\n".format(instance.ip_address, 
instance.private_ip_address))
@@ -356,6 +380,7 @@ def create(self, defn, check):
             
             self._private_ipv4 = instance.private_ip_address
             self._public_ipv4 = instance.ip_address
+            self._ssh_pinged = False
             self.write()
 
         # Wait until the instance is reachable via SSH.
@@ -471,7 +496,7 @@ def _delete_volume(self, volume_id):
 
 
     def destroy(self):
-        sys.stderr.write("destroying EC2 instance ‘{0}’... ".format(self.name))
+        sys.stderr.write("destroying EC2 machine ‘{0}’... ".format(self.name))
 
         instance = self._get_instance_by_id(self._instance_id)
         instance.terminate()        
diff --git a/nix/options.nix b/nix/options.nix
index 5596218..7865c84 100644
--- a/nix/options.nix
+++ b/nix/options.nix
@@ -206,7 +206,15 @@ in
       '';
     };
 
-    
+    deployment.ec2.elasticIPv4 = mkOption {
+      default = "";
+      example = "203.0.113.123";
+      type = types.uniq types.string;
+      description = ''
+        Elastic IPv4 address to be associated with this machine.
+      '';
+    };
+
     fileSystems = mkOption {
       options = {
         ec2 = mkOption {


================================================================

_______________________________________________
nix-commits mailing list
nix-comm...@lists.science.uu.nl
http://lists.science.uu.nl/mailman/listinfo/nix-commits

Reply via email to