CORD-3227: adding support for dual stack for R-CORD subscribers

Change-Id: Id25e7eb19a1cb60dfbd066ef4457e9b0245337c0
diff --git a/xos/synchronizer/models/models.py b/xos/synchronizer/models/models.py
index ccf5211..2fc2993 100644
--- a/xos/synchronizer/models/models.py
+++ b/xos/synchronizer/models/models.py
@@ -17,12 +17,29 @@
 import random
 
 from xos.exceptions import XOSValidationError, XOSProgrammingError, XOSPermissionDenied
-from models_decl import RCORDService_decl, RCORDSubscriber_decl
+from models_decl import RCORDService_decl, RCORDSubscriber_decl, RCORDIpAddress_decl
 
 class RCORDService(RCORDService_decl):
     class Meta:
         proxy = True
 
+class RCORDIpAddress(RCORDIpAddress_decl):
+    class Meta:
+        proxy = True
+
+    def save(self, *args, **kwargs):
+        try:
+            if ":" in self.ip:
+                # it's an IPv6 address
+                socket.inet_pton(socket.AF_INET6, self.ip)
+            else:
+                # it's an IPv4 address
+                socket.inet_pton(socket.AF_INET, self.ip)
+        except socket.error:
+            raise XOSValidationError("The IP specified is not valid: %s" % self.ip)
+        super(RCORDIpAddress, self).save(*args, **kwargs)
+        return
+
 class RCORDSubscriber(RCORDSubscriber_decl):
 
     class Meta:
@@ -61,7 +78,6 @@
         return used_tags
 
     def save(self, *args, **kwargs):
-
         self.validate_unique_service_specific_id(none_okay=True)
 
         # VSGServiceInstance will extract the creator from the Subscriber, as it needs a creator to create its
@@ -72,17 +88,10 @@
                 raise XOSProgrammingError("RCORDSubscriber's self.caller was not set")
             self.creator = self.caller
 
-        # validate IP Address
-        if hasattr(self, 'ip_address') and self.ip_address is not None:
-            try:
-                socket.inet_aton(self.ip_address)
-            except socket.error:
-                raise XOSValidationError("The ip_address you specified (%s) is not valid" % self.ip_address)
-
         # validate MAC Address
         if hasattr(self, 'mac_address') and self.mac_address is not None:
             if not re.match("[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", self.mac_address.lower()):
-                raise XOSValidationError("The mac_address you specified (%s) is not valid" % self.mac_address)
+                raise XOSValidationError("The MAC address specified is not valid: %s" % self.mac_address)
 
         # validate c_tag
         if hasattr(self, 'c_tag') and self.c_tag is not None: