Browse Source

Adds a README for GCE implementation.

Also, makes the GCEFirewallsDelegate class non-singleton.
chiniforooshan 10 years ago
parent
commit
4944f52b79

+ 30 - 0
cloudbridge/cloud/providers/gce/README.rst

@@ -0,0 +1,30 @@
+CloudBridge support for Google compute engine and cloud storage.
+
+Security Groups
+~~~~~~~~~~~~~~~
+CloudBridge API lets you control incoming traffic to VM instances by creating
+security groups, adding rules to security groups, and then assigning instances
+to security groups.
+
+GCE does this a little bit differently. GCE lets you assign `tags`_ to VM
+instances. Tags, then, can be used for networking purposes. In particular, you
+can create `firewall rules`_ to control incoming traffic to instances having a
+specific tag. So, to add GCE support to CloudBridge, we simulate security groups
+by tags.
+
+To make this more clear, let us consider the example of adding a rule to a
+security group. When you add a security group rule from the CloudBridge API to a
+security group ``sg``, what really happens, when the cloud provider is GCE, is
+that a firewall with one rule is created whose ``targetTags`` is ``[sg]``. This
+makes sure that the rule applies to all instances that have ``sg`` as a tag (in
+CloudBridge language instances belonging to the security group ``sg``).
+
+**Note**: This implementation does not take advantage of the full power of GCE
+firewall format and only creates firewalls with one rule and only sees firewalls
+with one rule.  This should be OK as long as all firewalls are created through
+the CloudBridge API.
+
+.. _`tags`: https://cloud.google.com/compute/docs/reference/latest/instances/
+   setTags
+.. _`firewall rules`: https://cloud.google.com/compute/docs/
+   networking#firewall_rules

+ 16 - 22
cloudbridge/cloud/providers/gce/resources.py

@@ -171,28 +171,21 @@ class GCERegion(BaseRegion):
 
 
 class GCEFirewallsDelegate(object):
-
-    _instance = None
-   
+  
     def __init__(self, provider):
-        if GCEFirewallsDelegate._instance is not None:
-            raise Exception('Use GCEFirewalls.instance() to instanciate.')
         self._provider = provider
         self._list_response = None
-        GCEFirewallsDelegate._instance = self
 
-    @staticmethod
-    def get_instance(provider):
-        if GCEFirewallsDelegate._instance is None:
-            GCEFirewallsDelegate(provider)
-        return GCEFirewallsDelegate._instance
- 
     @staticmethod
     def tag_id(tag):
         md5 = hashlib.md5()
         md5.update(tag.encode('ascii'))
         return md5.hexdigest()
 
+    @property
+    def provider(self):
+        return self._provider
+
     @property
     def tags(self):
         out = Set()
@@ -346,10 +339,10 @@ class GCEFirewallsDelegate(object):
 
 class GCESecurityGroup(BaseSecurityGroup):
 
-    def __init__(self, provider, tag, description=None):
-        super(GCESecurityGroup, self).__init__(provider, tag)
+    def __init__(self, delegate, tag, description=None):
+        super(GCESecurityGroup, self).__init__(delegate.provider, tag)
         self._description = description
-        self._delegate = GCEFirewallsDelegate.get_instance(provider)
+        self._delegate = delegate
 
     @property
     def id(self):
@@ -372,7 +365,7 @@ class GCESecurityGroup(BaseSecurityGroup):
     def rules(self):
         out = []
         for firewall in self._delegate.iter_firewalls(self._security_group):
-            out.append(GCESecurityGroupRule(self._provider, firewall['id']))
+            out.append(GCESecurityGroupRule(self._delegate, firewall['id']))
         return out
 
     @staticmethod
@@ -401,7 +394,7 @@ class GCESecurityGroup(BaseSecurityGroup):
                 self._security_group, ip_protocol, port, cidr_ip, src_tag)
         if firewall_id is None:
             return None
-        return GCESecurityGroupRule(self._provider, firewall_id)
+        return GCESecurityGroupRule(self._delegate, firewall_id)
 
     def to_json(self):
         attr = inspect.getmembers(self, lambda a: not(inspect.isroutine(a)))
@@ -417,16 +410,17 @@ class GCESecurityGroup(BaseSecurityGroup):
 
 class GCESecurityGroupRule(BaseSecurityGroupRule):
 
-    def __init__(self, provider, firewall_id):
-        super(GCESecurityGroupRule, self).__init__(provider, firewall_id, None)
-        self._delegate = GCEFirewallsDelegate.get_instance(provider)
+    def __init__(self, delegate, firewall_id):
+        super(GCESecurityGroupRule, self).__init__(
+                delegate.provider, firewall_id, None)
+        self._delegate = delegate
 
     @property
     def parent(self):
         info = self._delegate.get_firewall_info(self._rule)
         if info is None or 'target_tag' not in info:
             return None
-        return GCESecurityGroup(self._provider, info['target_tag'])
+        return GCESecurityGroup(self._delegate, info['target_tag'])
 
     @property
     def id(self):
@@ -481,7 +475,7 @@ class GCESecurityGroupRule(BaseSecurityGroupRule):
         info = self._delegate.get_firewall_info(self._rule)
         if info is None or 'source_tag' not in info:
             return None
-        return GCESecurityGroup(self._provider, info['source_tag'])
+        return GCESecurityGroup(self._delegate, info['source_tag'])
 
     def to_json(self):
         attr = inspect.getmembers(self, lambda a: not(inspect.isroutine(a)))

+ 5 - 5
cloudbridge/cloud/providers/gce/services.py

@@ -193,20 +193,20 @@ class GCESecurityGroupService(BaseSecurityGroupService):
 
     def __init__(self, provider):
         super(GCESecurityGroupService, self).__init__(provider)
-        self._delegate = GCEFirewallsDelegate.get_instance(provider)
+        self._delegate = GCEFirewallsDelegate(provider)
 
     def get(self, group_id):
         tag = self._delegate.get_tag_from_id(group_id)
-        return GCESecurityGroup(self.provider, tag) if tag is not None else None
+        return None if tag is None else GCESecurityGroup(self._delegate, tag)
 
     def list(self, limit=None, marker=None):
-        security_groups = [GCESecurityGroup(self.provider, x)
+        security_groups = [GCESecurityGroup(self._delegate, x)
                            for x in self._delegate.tags]
         return ClientPagedResultList(self.provider, security_groups,
                                      limit=limit, marker=marker)
 
     def create(self, name, description):
-        return GCESecurityGroup(self.provider, name, description)
+        return GCESecurityGroup(self._delegate, name, description)
 
     def find(self, name, limit=None, marker=None):
         """
@@ -215,7 +215,7 @@ class GCESecurityGroupService(BaseSecurityGroupService):
         is returned.
         """
         if self._delegate.has_tag(name):
-            return [GCESecurityGroup(self.provider, name)]
+            return [GCESecurityGroup(self._delegate, name)]
         return []
 
     def delete(self, group_id):