Merge lp:~soren/nova/secgroup-fixes into lp:~hudson-openstack/nova/trunk
- secgroup-fixes
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Vish Ishaya |
Approved revision: | 1532 |
Merged at revision: | 1586 |
Proposed branch: | lp:~soren/nova/secgroup-fixes |
Merge into: | lp:~hudson-openstack/nova/trunk |
Diff against target: |
152 lines (+78/-6) 5 files modified
nova/api/ec2/cloud.py (+17/-4) nova/db/sqlalchemy/api.py (+2/-0) nova/tests/api/ec2/test_cloud.py (+55/-0) nova/tests/test_api.py (+1/-1) nova/virt/libvirt/firewall.py (+3/-1) |
To merge this branch: | bzr merge lp:~soren/nova/secgroup-fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dan Prince (community) | Abstain | ||
Vish Ishaya (community) | Approve | ||
Christopher MacGown (community) | Approve | ||
Rick Harris (community) | Approve | ||
Review via email: mp+73794@code.launchpad.net |
Commit message
Description of the change
Fix a bug that would make spawning new instances fail if no port/protocol is given (for rules granting access for other security groups).
Soren Hansen (soren) wrote : | # |
Rick Harris (rconradharris) wrote : | # |
Good bug report, good patch. Nice job guys.
LGTM.
Vish Ishaya (vishvananda) wrote : | # |
This definitely fixes the linked bug, but it doesn't really address the way that security groups with no source ports are "supposed to" work.
According to this bug:
https:/
When you specify no source group, amazon actually creates 3 separate rules to allow all tcp udp and icmp traffic from the group. So it seems like empty ones actually should be converted.
I think there are two options for this:
a) create the 3 rules when we first receive the request and migrate old empty rules into three rules
b) continue to allow them to be created as is, but have a conversion that displays them as three rules to the client, and implements allow all when modifying ip tables.
If i read your patch correctly, you've done the part of b which makes them allow all traffic, but we still haven't made them display properly to the client. I think I'm ok with this if we add a bug for fixing the client display as well, although I am concerned about certain edge cases. Like what happens if someone tries to revoke one of the faux rules?
Vish Ishaya (vishvananda) wrote : | # |
Interesting. As far as I can tell, amazon does not support allowing ports from source groups. It is all or nothing:
euca2ools 1.3:
vishvananda@
test test None tcp 22 22 None
InvalidParamete
euca2ools 1.2:
vagrant@
GROUP test
PERMISSION test ALLOWS GRPNAME test
vagrant@
GROUP 911567224702 test test
PERMISSION 911567224702 test ALLOWS tcp 1 65535 GRPNAME test
PERMISSION 911567224702 test ALLOWS udp 1 65535 GRPNAME test
PERMISSION 911567224702 test ALLOWS icmp -1 -1 GRPNAME test
There doesn't seem to be any way to revoke just one of those rules. So I guess you're fix is fine as long as we change the display of the group to show all 3 on describe.
Christopher MacGown (0x44) wrote : | # |
This fix looks good, Approve with the change Vish suggested above.
Soren Hansen (soren) wrote : | # |
Vish, happy with it like this?
Vish Ishaya (vishvananda) wrote : | # |
This is good, although it might be nice to show both source groups with a specific protocol and without. Seems like it could be accomplished with another if inside the if rule.group_id:
if rule.protocol:
# show one rule
else:
# show three rules
Thoughts?
Vish
Soren Hansen (soren) wrote : | # |
> This is good, although it might be nice to show both source groups with a
> specific protocol and without. Seems like it could be accomplished with
> another if inside the if rule.group_id:
>
> if rule.protocol:
> # show one rule
> else:
> # show three rules
>
> Thoughts?
Depends. Do we want to allow source group filters with protocols and ports and stuff if EC2 doesn't?
Vish Ishaya (vishvananda) wrote : | # |
Extra feature!
Well it doesn't appear that you changed the actual rule creation code, so it will be supported as is regardless. It just won't display them properly.
Vish Ishaya (vishvananda) wrote : | # |
ping. I thought you mentioned in irc that you were going to make the change to show 3 or one rule?
OpenStack Infra (hudson-openstack) wrote : | # |
The attempt to merge lp:~soren/nova/secgroup-fixes into lp:nova failed. Below is the output from the failed tests.
CloudTestCase
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
OpenStack Infra (hudson-openstack) wrote : | # |
The attempt to merge lp:~soren/nova/secgroup-fixes into lp:nova failed. Below is the output from the failed tests.
CloudTestCase
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
Dan Prince (dan-prince) wrote : | # |
Soren:
I'm also getting a failure w/ this branch on Smokestack:
(nova.rpc): TRACE: File "/usr/lib/
(nova.rpc): TRACE: _execute(*cmd, run_as_root=True)
(nova.rpc): TRACE: File "/usr/lib/
(nova.rpc): TRACE: return utils.execute(*cmd, **kwargs)
(nova.rpc): TRACE: File "/usr/lib/
(nova.rpc): TRACE: cmd=' '.join(cmd))
(nova.rpc): TRACE: ProcessExecutio
(nova.rpc): TRACE: Command: sudo FLAGFILE=
(nova.rpc): TRACE: Exit code: 2
(nova.rpc): TRACE: Stdout: ''
(nova.rpc): TRACE: Stderr: '\ndnsmasq: failed to create listening socket for fe80::f4d9:
(nova.rpc): TRACE:
2011-09-16 17:29:27,469 ERROR nova.rpc [-] Returning exception Unexpected error while running command.
---
Let me know if you need more info.
Soren Hansen (soren) wrote : | # |
> Let me know if you need more info.
That would be great. I have no idea what might be causing this and I can't seem to reproduce it.
Dan Prince (dan-prince) wrote : | # |
Hey Soren,
My bad. The dnsmasq issue isn't from your branch at all. I get this on trunk as well. Sorry man, please disregard the above stack trace.
Preview Diff
1 | === modified file 'nova/api/ec2/cloud.py' |
2 | --- nova/api/ec2/cloud.py 2011-09-15 20:04:31 +0000 |
3 | +++ nova/api/ec2/cloud.py 2011-09-16 19:31:24 +0000 |
4 | @@ -594,18 +594,31 @@ |
5 | g['ipPermissions'] = [] |
6 | for rule in group.rules: |
7 | r = {} |
8 | - r['ipProtocol'] = rule.protocol |
9 | - r['fromPort'] = rule.from_port |
10 | - r['toPort'] = rule.to_port |
11 | r['groups'] = [] |
12 | r['ipRanges'] = [] |
13 | if rule.group_id: |
14 | source_group = db.security_group_get(context, rule.group_id) |
15 | r['groups'] += [{'groupName': source_group.name, |
16 | 'userId': source_group.project_id}] |
17 | + if rule.protocol: |
18 | + r['ipProtocol'] = rule.protocol |
19 | + r['fromPort'] = rule.from_port |
20 | + r['toPort'] = rule.to_port |
21 | + g['ipPermissions'] += [dict(r)] |
22 | + else: |
23 | + for protocol, min_port, max_port in (('icmp', -1, -1), |
24 | + ('tcp', 1, 65535), |
25 | + ('udp', 1, 65536)): |
26 | + r['ipProtocol'] = protocol |
27 | + r['fromPort'] = min_port |
28 | + r['toPort'] = max_port |
29 | + g['ipPermissions'] += [dict(r)] |
30 | else: |
31 | + r['ipProtocol'] = rule.protocol |
32 | + r['fromPort'] = rule.from_port |
33 | + r['toPort'] = rule.to_port |
34 | r['ipRanges'] += [{'cidrIp': rule.cidr}] |
35 | - g['ipPermissions'] += [r] |
36 | + g['ipPermissions'] += [r] |
37 | return g |
38 | |
39 | def _rule_args_to_dict(self, context, kwargs): |
40 | |
41 | === modified file 'nova/db/sqlalchemy/api.py' |
42 | --- nova/db/sqlalchemy/api.py 2011-09-14 20:57:15 +0000 |
43 | +++ nova/db/sqlalchemy/api.py 2011-09-16 19:31:24 +0000 |
44 | @@ -2827,12 +2827,14 @@ |
45 | result = session.query(models.SecurityGroupIngressRule).\ |
46 | filter_by(deleted=can_read_deleted(context)).\ |
47 | filter_by(parent_group_id=security_group_id).\ |
48 | + options(joinedload_all('grantee_group')).\ |
49 | all() |
50 | else: |
51 | # TODO(vish): Join to group and check for project_id |
52 | result = session.query(models.SecurityGroupIngressRule).\ |
53 | filter_by(deleted=False).\ |
54 | filter_by(parent_group_id=security_group_id).\ |
55 | + options(joinedload_all('grantee_group')).\ |
56 | all() |
57 | return result |
58 | |
59 | |
60 | === modified file 'nova/tests/api/ec2/test_cloud.py' |
61 | --- nova/tests/api/ec2/test_cloud.py 2011-09-13 21:04:13 +0000 |
62 | +++ nova/tests/api/ec2/test_cloud.py 2011-09-16 19:31:24 +0000 |
63 | @@ -305,6 +305,61 @@ |
64 | 'ip_protocol': u'tcp'}]} |
65 | self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs)) |
66 | |
67 | + def test_describe_security_group_ingress_groups(self): |
68 | + kwargs = {'project_id': self.context.project_id, 'name': 'test'} |
69 | + sec1 = db.security_group_create(self.context, kwargs) |
70 | + sec2 = db.security_group_create(self.context, |
71 | + {'project_id': 'someuser', |
72 | + 'name': 'somegroup1'}) |
73 | + sec3 = db.security_group_create(self.context, |
74 | + {'project_id': 'someuser', |
75 | + 'name': 'othergroup2'}) |
76 | + authz = self.cloud.authorize_security_group_ingress |
77 | + kwargs = {'ip_permissions': [ |
78 | + {'groups': {'1': {'user_id': u'someuser', |
79 | + 'group_name': u'somegroup1'}}}, |
80 | + {'ip_protocol': 'tcp', |
81 | + 'from_port': 80, |
82 | + 'to_port': 80, |
83 | + 'groups': {'1': {'user_id': u'someuser', |
84 | + 'group_name': u'othergroup2'}}}]} |
85 | + self.assertTrue(authz(self.context, group_name=sec1['name'], **kwargs)) |
86 | + describe = self.cloud.describe_security_groups |
87 | + groups = describe(self.context, group_name=['test']) |
88 | + self.assertEquals(len(groups['securityGroupInfo']), 1) |
89 | + actual_rules = groups['securityGroupInfo'][0]['ipPermissions'] |
90 | + self.assertEquals(len(actual_rules), 4) |
91 | + expected_rules = [{'fromPort': -1, |
92 | + 'groups': [{'groupName': 'somegroup1', |
93 | + 'userId': 'someuser'}], |
94 | + 'ipProtocol': 'icmp', |
95 | + 'ipRanges': [], |
96 | + 'toPort': -1}, |
97 | + {'fromPort': 1, |
98 | + 'groups': [{'groupName': u'somegroup1', |
99 | + 'userId': u'someuser'}], |
100 | + 'ipProtocol': 'tcp', |
101 | + 'ipRanges': [], |
102 | + 'toPort': 65535}, |
103 | + {'fromPort': 1, |
104 | + 'groups': [{'groupName': u'somegroup1', |
105 | + 'userId': u'someuser'}], |
106 | + 'ipProtocol': 'udp', |
107 | + 'ipRanges': [], |
108 | + 'toPort': 65536}, |
109 | + {'fromPort': 80, |
110 | + 'groups': [{'groupName': u'othergroup2', |
111 | + 'userId': u'someuser'}], |
112 | + 'ipProtocol': u'tcp', |
113 | + 'ipRanges': [], |
114 | + 'toPort': 80}] |
115 | + for rule in expected_rules: |
116 | + self.assertTrue(rule in actual_rules) |
117 | + |
118 | + db.security_group_destroy(self.context, sec3['id']) |
119 | + db.security_group_destroy(self.context, sec2['id']) |
120 | + db.security_group_destroy(self.context, sec1['id']) |
121 | + |
122 | def test_revoke_security_group_ingress(self): |
123 | kwargs = {'project_id': self.context.project_id, 'name': 'test'} |
124 | sec = db.security_group_create(self.context, kwargs) |
125 | |
126 | === modified file 'nova/tests/test_api.py' |
127 | --- nova/tests/test_api.py 2011-08-12 04:03:37 +0000 |
128 | +++ nova/tests/test_api.py 2011-09-16 19:31:24 +0000 |
129 | @@ -515,7 +515,7 @@ |
130 | # be good enough for that. |
131 | for group in rv: |
132 | if group.name == security_group_name: |
133 | - self.assertEquals(len(group.rules), 1) |
134 | + self.assertEquals(len(group.rules), 3) |
135 | self.assertEquals(len(group.rules[0].grants), 1) |
136 | self.assertEquals(str(group.rules[0].grants[0]), '%s-%s' % |
137 | (other_security_group_name, 'fake')) |
138 | |
139 | === modified file 'nova/virt/libvirt/firewall.py' |
140 | --- nova/virt/libvirt/firewall.py 2011-08-26 17:38:20 +0000 |
141 | +++ nova/virt/libvirt/firewall.py 2011-09-16 19:31:24 +0000 |
142 | @@ -663,7 +663,9 @@ |
143 | if version == 6 and rule.protocol == 'icmp': |
144 | protocol = 'icmpv6' |
145 | |
146 | - args = ['-j ACCEPT', '-p', protocol] |
147 | + args = ['-j ACCEPT'] |
148 | + if protocol: |
149 | + args += ['-p', protocol] |
150 | |
151 | if protocol in ['udp', 'tcp']: |
152 | if rule.from_port == rule.to_port: |
https:/ /bugs.launchpad .net/nova/ +bug/838419/ comments/ 5 says it works.