diff options
| -rw-r--r-- | nova/auth/manager.py | 6 | ||||
| -rw-r--r-- | nova/db/api.py | 22 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/api.py | 38 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/models.py | 54 | ||||
| -rw-r--r-- | nova/endpoint/cloud.py | 14 | ||||
| -rw-r--r-- | nova/tests/api_unittest.py | 34 |
6 files changed, 160 insertions, 8 deletions
diff --git a/nova/auth/manager.py b/nova/auth/manager.py index d5fbec7c5..6aa5721c8 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -640,11 +640,17 @@ class AuthManager(object): with self.driver() as drv: user_dict = drv.create_user(name, access, secret, admin) if user_dict: + db.security_group_create(context={}, + values={ 'name' : 'default', + 'description' : 'default', + 'user_id' : name }) return User(**user_dict) def delete_user(self, user): """Deletes a user""" with self.driver() as drv: + for security_group in db.security_group_get_by_user(context = {}, user_id=user.id): + db.security_group_destroy({}, security_group.id) drv.delete_user(User.safe_id(user)) def generate_key_pair(self, user, key_name): diff --git a/nova/db/api.py b/nova/db/api.py index b49707392..b67e3afe0 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -442,3 +442,25 @@ def volume_update(context, volume_id, values): """ return IMPL.volume_update(context, volume_id, values) + +#################### + + +def security_group_create(context, values): + """Create a new security group""" + return IMPL.security_group_create(context, values) + + +def security_group_get_by_instance(context, instance_id): + """Get security groups to which the instance is assigned""" + return IMPL.security_group_get_by_instance(context, instance_id) + + +def security_group_get_by_user(context, user_id): + """Get security groups owned by the given user""" + return IMPL.security_group_get_by_user(context, user_id) + + +def security_group_destroy(context, security_group_id): + """Deletes a security group""" + return IMPL.security_group_destroy(context, security_group_id) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 5172b87b3..d790d3fac 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -581,3 +581,41 @@ def volume_update(context, volume_id, values): for (key, value) in values.iteritems(): volume_ref[key] = value volume_ref.save() + + +################### + + +def security_group_create(_context, values): + security_group_ref = models.SecurityGroup() + for (key, value) in values.iteritems(): + security_group_ref[key] = value + security_group_ref.save() + return security_group_ref + + +def security_group_get_by_instance(_context, instance_id): + with managed_session() as session: + return session.query(models.Instance) \ + .get(instance_id) \ + .security_groups \ + .all() + + +def security_group_get_by_user(_context, user_id): + with managed_session() as session: + return session.query(models.SecurityGroup) \ + .filter_by(user_id=user_id) \ + .filter_by(deleted=False) \ + .all() + +def security_group_destroy(_context, security_group_id): + with managed_session() as session: + security_group = session.query(models.SecurityGroup) \ + .get(security_group_id) + security_group.delete(session=session) + +def security_group_get_all(_context): + return models.SecurityGroup.all() + + diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 310d4640e..28c25bfbc 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -26,7 +26,7 @@ import datetime # TODO(vish): clean up these imports from sqlalchemy.orm import relationship, backref, validates, exc from sqlalchemy.sql import func -from sqlalchemy import Column, Integer, String +from sqlalchemy import Column, Integer, String, Table from sqlalchemy import ForeignKey, DateTime, Boolean, Text from sqlalchemy.ext.declarative import declarative_base @@ -292,6 +292,58 @@ class ExportDevice(BASE, NovaBase): uselist=False)) +security_group_instance_association = Table('security_group_instance_association', + BASE.metadata, + Column('security_group_id', Integer, + ForeignKey('security_group.id')), + Column('instance_id', Integer, + ForeignKey('instances.id'))) + +class SecurityGroup(BASE, NovaBase): + """Represents a security group""" + __tablename__ = 'security_group' + id = Column(Integer, primary_key=True) + + name = Column(String(255)) + description = Column(String(255)) + + user_id = Column(String(255)) + project_id = Column(String(255)) + + instances = relationship(Instance, + secondary=security_group_instance_association, + backref='security_groups') + + @property + def user(self): + return auth.manager.AuthManager().get_user(self.user_id) + + @property + def project(self): + return auth.manager.AuthManager().get_project(self.project_id) + + +class SecurityGroupIngressRule(BASE, NovaBase): + """Represents a rule in a security group""" + __tablename__ = 'security_group_rules' + id = Column(Integer, primary_key=True) + + parent_security_group = Column(Integer, ForeignKey('security_group.id')) + protocol = Column(String(5)) # "tcp", "udp", or "icmp" + fromport = Column(Integer) + toport = Column(Integer) + + # Note: This is not the parent SecurityGroup's owner. It's the owner of + # the SecurityGroup we're granting access. + user_id = Column(String(255)) + group_id = Column(Integer, ForeignKey('security_group.id')) + + @property + def user(self): + return auth.manager.AuthManager().get_user(self.user_id) + + cidr = Column(String(255)) + class Network(BASE, NovaBase): """Represents a network""" __tablename__ = 'networks' diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index 44997be59..7df8bd081 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -212,10 +212,12 @@ class CloudController(object): return True @rbac.allow('all') - def describe_security_groups(self, context, group_names, **kwargs): - groups = {'securityGroupSet': []} + def describe_security_groups(self, context, **kwargs): + groups = {'securityGroupSet': + [{ 'groupDescription': group.description, + 'groupName' : group.name, + 'ownerId': context.user.id } for group in db.security_group_get_by_user(context, context.user.id) ] } - # Stubbed for now to unblock other things. return groups @rbac.allow('netadmin') @@ -223,7 +225,11 @@ class CloudController(object): return True @rbac.allow('netadmin') - def create_security_group(self, context, group_name, **kwargs): + def create_security_group(self, context, group_name, group_description): + db.security_group_create(context, + values = { 'user_id' : context.user.id, + 'name': group_name, + 'description': group_description }) return True @rbac.allow('netadmin') diff --git a/nova/tests/api_unittest.py b/nova/tests/api_unittest.py index 462d1b295..87d99607d 100644 --- a/nova/tests/api_unittest.py +++ b/nova/tests/api_unittest.py @@ -185,6 +185,9 @@ class ApiEc2TestCase(test.BaseTestCase): self.host = '127.0.0.1' self.app = api.APIServerApplication({'Cloud': self.cloud}) + + def expect_http(self, host=None, is_secure=False): + """Returns a new EC2 connection""" self.ec2 = boto.connect_ec2( aws_access_key_id='fake', aws_secret_access_key='fake', @@ -194,9 +197,6 @@ class ApiEc2TestCase(test.BaseTestCase): path='/services/Cloud') self.mox.StubOutWithMock(self.ec2, 'new_http_connection') - - def expect_http(self, host=None, is_secure=False): - """Returns a new EC2 connection""" http = FakeHttplibConnection( self.app, '%s:%d' % (self.host, FLAGS.cc_port), False) # pylint: disable-msg=E1103 @@ -231,3 +231,31 @@ class ApiEc2TestCase(test.BaseTestCase): self.assertEquals(len(results), 1) self.manager.delete_project(project) self.manager.delete_user(user) + + def test_get_all_security_groups(self): + """Test that operations on security groups stick""" + self.expect_http() + self.mox.ReplayAll() + security_group_name = "".join(random.choice("sdiuisudfsdcnpaqwertasd") \ + for x in range(random.randint(4, 8))) + user = self.manager.create_user('fake', 'fake', 'fake', admin=True) + project = self.manager.create_project('fake', 'fake', 'fake') + + rv = self.ec2.get_all_security_groups() + self.assertEquals(len(rv), 1) + self.assertEquals(rv[0].name, 'default') + + self.expect_http() + self.mox.ReplayAll() + + self.ec2.create_security_group(security_group_name, 'test group') + + self.expect_http() + self.mox.ReplayAll() + + rv = self.ec2.get_all_security_groups() + self.assertEquals(len(rv), 2) + self.assertTrue(security_group_name in [group.name for group in rv]) + + self.manager.delete_project(project) + self.manager.delete_user(user) |
