Merge lp:~vishvananda/nova/ha-net into lp:~hudson-openstack/nova/trunk
- ha-net
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Devin Carlen |
Approved revision: | 1266 |
Merged at revision: | 1293 |
Proposed branch: | lp:~vishvananda/nova/ha-net |
Merge into: | lp:~hudson-openstack/nova/trunk |
Diff against target: |
1104 lines (+280/-175) 15 files modified
bin/nova-dhcpbridge (+1/-1) bin/nova-manage (+12/-7) nova/compute/manager.py (+9/-8) nova/db/api.py (+12/-6) nova/db/sqlalchemy/api.py (+32/-11) nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py (+44/-0) nova/db/sqlalchemy/models.py (+2/-0) nova/exception.py (+5/-0) nova/network/api.py (+14/-4) nova/network/linux_net.py (+20/-20) nova/network/manager.py (+121/-100) nova/tests/__init__.py (+2/-1) nova/tests/test_libvirt.py (+1/-0) nova/tests/test_network.py (+4/-15) nova/virt/libvirt/connection.py (+1/-2) |
To merge this branch: | bzr merge lp:~vishvananda/nova/ha-net |
Related bugs: | |
Related blueprints: |
High Availability FlatDHCP
(Medium)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Devin Carlen (community) | Approve | ||
Dan Prince (community) | Approve | ||
Koji Iida (community) | Needs Information | ||
Review via email: mp+67078@code.launchpad.net |
Commit message
Adds HA networking (multi_host) option to networks.
* Adds extra flag for network creation: multi_host.
* Multi hosts networks will send all network related commands to the host that the vm is on.
* Requires nova-network to be run on every compute host.
* Non multi_host networks work the same way.
* Moved extra db access out of linux_net (there is still a little in the dhcp leases part that should probably be moved)
* Fixed the logic on auto_assign which was messed up
Description of the change
Adds HA networking option to networks.
* Adds extra flag for network creation: multi_host.
* Multi hosts networks will send all network related commands to the host that the vm is on.
* Requires nova-network to be run on every compute host.
* Non multi_host networks work the same way.
Other cleanup:
* Moved extra db access out of linux_net (there is still a little in the dhcp leases part that should probably be moved)
* Fixed the logic on auto_assign which was messed up
Potential issues:
* The flag version means I'm checking for multi_host in a number of places. Ideas for changes here welcome.
* Nova-manage positional changes are annoying, we need the kwarg version in place
* No tests added. Open to suggestions on some specific tests that could be added.
Jason Kölker (jason-koelker) wrote : | # |
Mandell (mdegerne) wrote : | # |
I like Jason's suggestion, although I would want to check for "y" as well.
I'm a bit concerned about the way which _on_set_
Lucky (luckythetourist) wrote : | # |
Other than the above I have a single nit:
On L583-584 the order of operations should be explicit
e.g.,
(foo and bar) or baz
or
foo and (bar or baz)
Vish Ishaya (vishvananda) wrote : | # |
On Jul 7, 2011, at 3:13 PM, Mandell wrote:
> I like Jason's suggestion, although I would want to check for "y" as well.
>
Will fix. I was following the use of T in a few other places, so switching the others should be done in the branch that is adding in better opt parsing
> I'm a bit concerned about the way which _on_set_
My current mental model says HA networks belong to all hosts. I think this is the most common use case. That said, I can change the init host to look for ha networks that already have an ip on this host, and only on_set_network_host there, then I can also call it from the associate call in _get_dhcp_ip. That should make the network only show up on the host if it is being used.
Vish
Vish Ishaya (vishvananda) wrote : | # |
Cleaned up stuff and made changes to make setup of networks automatic if an ip is allocated and the network has not been setup yet.
Koji Iida (iida-koji) wrote : | # |
I have a question.
I can't boot a instance under VlanManager and multi_host set to false.
2011-07-16 13:21:37,094 DEBUG nova.network.
2011-07-16 13:21:37,094 DEBUG nova.network.
2011-07-16 13:21:37,102 ERROR nova [-] Exception during message handling
(nova): TRACE: Traceback (most recent call last):
(nova): TRACE: File "/opt2/
(nova): TRACE: rval = node_func(
(nova): TRACE: File "/opt2/
(nova): TRACE: ips = super(FloatingIP, self).allocate_
(nova): TRACE: File "/opt2/
(nova): TRACE: project_id)
(nova): TRACE: File "/opt2/
(nova): TRACE: return self.db.
(nova): TRACE: File "/opt2/
(nova): TRACE: return IMPL.project_
(nova): TRACE: File "/opt2/
(nova): TRACE: return f(*args, **kwargs)
(nova): TRACE: File "/opt2/
(nova): TRACE: return [network_
(nova): TRACE: File "/opt2/
(nova): TRACE: return f(*args, **kwargs)
(nova): TRACE: File "/opt2/
(nova): TRACE: raise db.NoMoreNetworks()
(nova): TRACE: NoMoreNetworks: None
(nova): TRACE:
615 - # setup any new networks which have been created
616 - self.set_
set_network_hosts() is removed from periodic_tasks.
Are there any other mechanisms to allocate host to network?
Vish Ishaya (vishvananda) wrote : | # |
Hmm, this could be a bug. It is supposed to set_network_host in the allocate_
Vish
On Jul 15, 2011, at 11:33 PM, Koji Iida wrote:
> Review: Needs Information
> I have a question.
>
> I can't boot a instance under VlanManager and multi_host set to false.
>
> 2011-07-16 13:21:37,094 DEBUG nova.network.
> 2011-07-16 13:21:37,094 DEBUG nova.network.
> 2011-07-16 13:21:37,102 ERROR nova [-] Exception during message handling
> (nova): TRACE: Traceback (most recent call last):
> (nova): TRACE: File "/opt2/
> (nova): TRACE: rval = node_func(
> (nova): TRACE: File "/opt2/
> (nova): TRACE: ips = super(FloatingIP, self).allocate_
> (nova): TRACE: File "/opt2/
> (nova): TRACE: project_id)
> (nova): TRACE: File "/opt2/
> (nova): TRACE: return self.db.
> (nova): TRACE: File "/opt2/
> (nova): TRACE: return IMPL.project_
> (nova): TRACE: File "/opt2/
> (nova): TRACE: return f(*args, **kwargs)
> (nova): TRACE: File "/opt2/
> (nova): TRACE: return [network_
> (nova): TRACE: File "/opt2/
> (nova): TRACE: return f(*args, **kwargs)
> (nova): TRACE: File "/opt2/
> (nova): TRACE: raise db.NoMoreNetworks()
> (nova): TRACE: NoMoreNetworks: None
> (nova): TRACE:
>
>
> 615 - # setup any new networks which have been created
> 616 - self.set_
>
> set_network_hosts() is removed from periodic_tasks.
> Are there any other mechanisms to allocate host to network?
>
>
>
>
> --
> https:/
> You are the owner of lp:~vishvananda/nova/ha-net.
- 1259. By Vish Ishaya
-
fix issues that were breaking vlan mode
Vish Ishaya (vishvananda) wrote : | # |
koji. I fixed the issue with vlan mode. Can you try again?
- 1260. By Vish Ishaya
-
merged trunk
- 1261. By Vish Ishaya
-
change migration number
- 1262. By Vish Ishaya
-
fix bad merge
- 1263. By Vish Ishaya
-
missed the vpn kwarg in rpc
Dan Prince (dan-prince) wrote : | # |
Hey Vish,
Would you be up for adding a 'downgrade' to this migration. I know not all of our migrations have them but I'd prefer to follow that model.
Otherwise looks good. All functional tests appear to be passing on Smokestack too.
- 1264. By Vish Ishaya
-
add downgrade
Vish Ishaya (vishvananda) wrote : | # |
Hey Dan,
Added a downgrade.
Dan Prince (dan-prince) wrote : | # |
Great. Looks good.
- 1265. By Vish Ishaya
-
merged trunk
- 1266. By Vish Ishaya
-
pep8
Do Dinh Thang (thangdd-it49) wrote : | # |
Hi Vish,
I setup & run nova-network in multi_host mode.
when I restart service nova-network on Node1, i must rerun "euca-associate
Is it a bug?
Vish Ishaya (vishvananda) wrote : | # |
It should reassociate the floating ips on reboot. This sounds like a bug.
On Aug 16, 2011, at 2:11 AM, Do Dinh Thang wrote:
> Hi Vish,
> I setup & run nova-network in multi_host mode.
> when I restart service nova-network on Node1, i must rerun "euca-associate
> Is it a bug?
> --
> https:/
> You are the owner of lp:~vishvananda/nova/ha-net.
Preview Diff
1 | === modified file 'bin/nova-dhcpbridge' | |||
2 | --- bin/nova-dhcpbridge 2011-07-11 20:31:39 +0000 | |||
3 | +++ bin/nova-dhcpbridge 2011-07-20 18:28:31 +0000 | |||
4 | @@ -91,7 +91,7 @@ | |||
5 | 91 | """Get the list of hosts for an interface.""" | 91 | """Get the list of hosts for an interface.""" |
6 | 92 | ctxt = context.get_admin_context() | 92 | ctxt = context.get_admin_context() |
7 | 93 | network_ref = db.network_get_by_bridge(ctxt, interface) | 93 | network_ref = db.network_get_by_bridge(ctxt, interface) |
9 | 94 | return linux_net.get_dhcp_leases(ctxt, network_ref['id']) | 94 | return linux_net.get_dhcp_leases(ctxt, network_ref) |
10 | 95 | 95 | ||
11 | 96 | 96 | ||
12 | 97 | def main(): | 97 | def main(): |
13 | 98 | 98 | ||
14 | === modified file 'bin/nova-manage' | |||
15 | --- bin/nova-manage 2011-07-18 19:09:39 +0000 | |||
16 | +++ bin/nova-manage 2011-07-20 18:28:31 +0000 | |||
17 | @@ -479,7 +479,7 @@ | |||
18 | 479 | except db.api.NoMoreNetworks: | 479 | except db.api.NoMoreNetworks: |
19 | 480 | print _('No more networks available. If this is a new ' | 480 | print _('No more networks available. If this is a new ' |
20 | 481 | 'installation, you need\nto call something like this:\n\n' | 481 | 'installation, you need\nto call something like this:\n\n' |
22 | 482 | ' nova-manage network create 10.0.0.0/8 10 64\n\n') | 482 | ' nova-manage network create pvt 10.0.0.0/8 10 64\n\n') |
23 | 483 | except exception.ProcessExecutionError, e: | 483 | except exception.ProcessExecutionError, e: |
24 | 484 | print e | 484 | print e |
25 | 485 | print _("The above error may show that the certificate db has not " | 485 | print _("The above error may show that the certificate db has not " |
26 | @@ -500,7 +500,7 @@ | |||
27 | 500 | if host is None: | 500 | if host is None: |
28 | 501 | fixed_ips = db.fixed_ip_get_all(ctxt) | 501 | fixed_ips = db.fixed_ip_get_all(ctxt) |
29 | 502 | else: | 502 | else: |
31 | 503 | fixed_ips = db.fixed_ip_get_all_by_host(ctxt, host) | 503 | fixed_ips = db.fixed_ip_get_all_by_instance_host(ctxt, host) |
32 | 504 | except exception.NotFound as ex: | 504 | except exception.NotFound as ex: |
33 | 505 | print "error: %s" % ex | 505 | print "error: %s" % ex |
34 | 506 | sys.exit(2) | 506 | sys.exit(2) |
35 | @@ -564,17 +564,17 @@ | |||
36 | 564 | """Class for managing networks.""" | 564 | """Class for managing networks.""" |
37 | 565 | 565 | ||
38 | 566 | def create(self, label=None, fixed_range=None, num_networks=None, | 566 | def create(self, label=None, fixed_range=None, num_networks=None, |
40 | 567 | network_size=None, vlan_start=None, | 567 | network_size=None, multi_host=None, vlan_start=None, |
41 | 568 | vpn_start=None, fixed_range_v6=None, gateway_v6=None, | 568 | vpn_start=None, fixed_range_v6=None, gateway_v6=None, |
42 | 569 | flat_network_bridge=None, bridge_interface=None): | 569 | flat_network_bridge=None, bridge_interface=None): |
43 | 570 | """Creates fixed ips for host by range | 570 | """Creates fixed ips for host by range |
44 | 571 | arguments: label, fixed_range, [num_networks=FLAG], | 571 | arguments: label, fixed_range, [num_networks=FLAG], |
46 | 572 | [network_size=FLAG], [vlan_start=FLAG], | 572 | [network_size=FLAG], [multi_host=FLAG], [vlan_start=FLAG], |
47 | 573 | [vpn_start=FLAG], [fixed_range_v6=FLAG], [gateway_v6=FLAG], | 573 | [vpn_start=FLAG], [fixed_range_v6=FLAG], [gateway_v6=FLAG], |
48 | 574 | [flat_network_bridge=FLAG], [bridge_interface=FLAG] | 574 | [flat_network_bridge=FLAG], [bridge_interface=FLAG] |
52 | 575 | If you wish to use a later argument fill in the gaps with 0s | 575 | If you wish to use a later argument fill in the gaps with ""s |
53 | 576 | Ex: network create private 10.0.0.0/8 1 15 0 0 0 0 xenbr1 eth1 | 576 | Ex: network create private 10.0.0.0/8 1 16 T "" "" "" "" xenbr1 eth1 |
54 | 577 | network create private 10.0.0.0/8 1 15 | 577 | network create private 10.0.0.0/8 1 16 |
55 | 578 | """ | 578 | """ |
56 | 579 | if not label: | 579 | if not label: |
57 | 580 | msg = _('a label (ex: public) is required to create networks.') | 580 | msg = _('a label (ex: public) is required to create networks.') |
58 | @@ -589,6 +589,10 @@ | |||
59 | 589 | num_networks = FLAGS.num_networks | 589 | num_networks = FLAGS.num_networks |
60 | 590 | if not network_size: | 590 | if not network_size: |
61 | 591 | network_size = FLAGS.network_size | 591 | network_size = FLAGS.network_size |
62 | 592 | if not multi_host: | ||
63 | 593 | multi_host = FLAGS.multi_host | ||
64 | 594 | else: | ||
65 | 595 | multi_host = multi_host == 'T' | ||
66 | 592 | if not vlan_start: | 596 | if not vlan_start: |
67 | 593 | vlan_start = FLAGS.vlan_start | 597 | vlan_start = FLAGS.vlan_start |
68 | 594 | if not vpn_start: | 598 | if not vpn_start: |
69 | @@ -607,6 +611,7 @@ | |||
70 | 607 | net_manager.create_networks(context.get_admin_context(), | 611 | net_manager.create_networks(context.get_admin_context(), |
71 | 608 | label=label, | 612 | label=label, |
72 | 609 | cidr=fixed_range, | 613 | cidr=fixed_range, |
73 | 614 | multi_host=multi_host, | ||
74 | 610 | num_networks=int(num_networks), | 615 | num_networks=int(num_networks), |
75 | 611 | network_size=int(network_size), | 616 | network_size=int(network_size), |
76 | 612 | vlan_start=int(vlan_start), | 617 | vlan_start=int(vlan_start), |
77 | 613 | 618 | ||
78 | === modified file 'nova/compute/manager.py' | |||
79 | --- nova/compute/manager.py 2011-07-19 20:21:39 +0000 | |||
80 | +++ nova/compute/manager.py 2011-07-20 18:28:31 +0000 | |||
81 | @@ -77,8 +77,6 @@ | |||
82 | 77 | flags.DEFINE_integer("rescue_timeout", 0, | 77 | flags.DEFINE_integer("rescue_timeout", 0, |
83 | 78 | "Automatically unrescue an instance after N seconds." | 78 | "Automatically unrescue an instance after N seconds." |
84 | 79 | " Set to 0 to disable.") | 79 | " Set to 0 to disable.") |
85 | 80 | flags.DEFINE_bool('auto_assign_floating_ip', False, | ||
86 | 81 | 'Autoassigning floating ip to VM') | ||
87 | 82 | flags.DEFINE_integer('host_state_interval', 120, | 80 | flags.DEFINE_integer('host_state_interval', 120, |
88 | 83 | 'Interval in seconds for querying the host status') | 81 | 'Interval in seconds for querying the host status') |
89 | 84 | 82 | ||
90 | @@ -274,16 +272,19 @@ | |||
91 | 274 | """Launch a new instance with specified options.""" | 272 | """Launch a new instance with specified options.""" |
92 | 275 | context = context.elevated() | 273 | context = context.elevated() |
93 | 276 | instance = self.db.instance_get(context, instance_id) | 274 | instance = self.db.instance_get(context, instance_id) |
94 | 277 | instance.injected_files = kwargs.get('injected_files', []) | ||
95 | 278 | instance.admin_pass = kwargs.get('admin_password', None) | ||
96 | 279 | if instance['name'] in self.driver.list_instances(): | 275 | if instance['name'] in self.driver.list_instances(): |
97 | 280 | raise exception.Error(_("Instance has already been created")) | 276 | raise exception.Error(_("Instance has already been created")) |
98 | 281 | LOG.audit(_("instance %s: starting..."), instance_id, | 277 | LOG.audit(_("instance %s: starting..."), instance_id, |
99 | 282 | context=context) | 278 | context=context) |
104 | 283 | self.db.instance_update(context, | 279 | updates = {} |
105 | 284 | instance_id, | 280 | updates['host'] = self.host |
106 | 285 | {'host': self.host, 'launched_on': self.host}) | 281 | updates['launched_on'] = self.host |
107 | 286 | 282 | # NOTE(vish): used by virt but not in database | |
108 | 283 | updates['injected_files'] = kwargs.get('injected_files', []) | ||
109 | 284 | updates['admin_pass'] = kwargs.get('admin_password', None) | ||
110 | 285 | instance = self.db.instance_update(context, | ||
111 | 286 | instance_id, | ||
112 | 287 | updates) | ||
113 | 287 | self.db.instance_set_state(context, | 288 | self.db.instance_set_state(context, |
114 | 288 | instance_id, | 289 | instance_id, |
115 | 289 | power_state.NOSTATE, | 290 | power_state.NOSTATE, |
116 | 290 | 291 | ||
117 | === modified file 'nova/db/api.py' | |||
118 | --- nova/db/api.py 2011-07-08 03:07:58 +0000 | |||
119 | +++ nova/db/api.py 2011-07-20 18:28:31 +0000 | |||
120 | @@ -332,13 +332,14 @@ | |||
121 | 332 | return IMPL.fixed_ip_associate(context, address, instance_id) | 332 | return IMPL.fixed_ip_associate(context, address, instance_id) |
122 | 333 | 333 | ||
123 | 334 | 334 | ||
126 | 335 | def fixed_ip_associate_pool(context, network_id, instance_id): | 335 | def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None): |
127 | 336 | """Find free ip in network and associate it to instance. | 336 | """Find free ip in network and associate it to instance or host. |
128 | 337 | 337 | ||
129 | 338 | Raises if one is not available. | 338 | Raises if one is not available. |
130 | 339 | 339 | ||
131 | 340 | """ | 340 | """ |
133 | 341 | return IMPL.fixed_ip_associate_pool(context, network_id, instance_id) | 341 | return IMPL.fixed_ip_associate_pool(context, network_id, |
134 | 342 | instance_id, host) | ||
135 | 342 | 343 | ||
136 | 343 | 344 | ||
137 | 344 | def fixed_ip_create(context, values): | 345 | def fixed_ip_create(context, values): |
138 | @@ -361,9 +362,9 @@ | |||
139 | 361 | return IMPL.fixed_ip_get_all(context) | 362 | return IMPL.fixed_ip_get_all(context) |
140 | 362 | 363 | ||
141 | 363 | 364 | ||
145 | 364 | def fixed_ip_get_all_by_host(context, host): | 365 | def fixed_ip_get_all_by_instance_host(context, host): |
146 | 365 | """Get all defined fixed ips used by a host.""" | 366 | """Get all allocated fixed ips filtered by instance host.""" |
147 | 366 | return IMPL.fixed_ip_get_all_by_host(context, host) | 367 | return IMPL.fixed_ip_get_all_instance_by_host(context, host) |
148 | 367 | 368 | ||
149 | 368 | 369 | ||
150 | 369 | def fixed_ip_get_by_address(context, address): | 370 | def fixed_ip_get_by_address(context, address): |
151 | @@ -376,6 +377,11 @@ | |||
152 | 376 | return IMPL.fixed_ip_get_by_instance(context, instance_id) | 377 | return IMPL.fixed_ip_get_by_instance(context, instance_id) |
153 | 377 | 378 | ||
154 | 378 | 379 | ||
155 | 380 | def fixed_ip_get_by_network_host(context, network_id, host): | ||
156 | 381 | """Get fixed ip for a host in a network.""" | ||
157 | 382 | return IMPL.fixed_ip_get_by_network_host(context, network_id, host) | ||
158 | 383 | |||
159 | 384 | |||
160 | 379 | def fixed_ip_get_by_virtual_interface(context, vif_id): | 385 | def fixed_ip_get_by_virtual_interface(context, vif_id): |
161 | 380 | """Get fixed ips by virtual interface or raise if none exist.""" | 386 | """Get fixed ips by virtual interface or raise if none exist.""" |
162 | 381 | return IMPL.fixed_ip_get_by_virtual_interface(context, vif_id) | 387 | return IMPL.fixed_ip_get_by_virtual_interface(context, vif_id) |
163 | 382 | 388 | ||
164 | === modified file 'nova/db/sqlalchemy/api.py' | |||
165 | --- nova/db/sqlalchemy/api.py 2011-07-18 23:42:02 +0000 | |||
166 | +++ nova/db/sqlalchemy/api.py 2011-07-20 18:28:31 +0000 | |||
167 | @@ -18,7 +18,6 @@ | |||
168 | 18 | """ | 18 | """ |
169 | 19 | Implementation of SQLAlchemy backend. | 19 | Implementation of SQLAlchemy backend. |
170 | 20 | """ | 20 | """ |
171 | 21 | import traceback | ||
172 | 22 | import warnings | 21 | import warnings |
173 | 23 | 22 | ||
174 | 24 | from nova import db | 23 | from nova import db |
175 | @@ -33,7 +32,6 @@ | |||
176 | 33 | from sqlalchemy.exc import IntegrityError | 32 | from sqlalchemy.exc import IntegrityError |
177 | 34 | from sqlalchemy.orm import joinedload | 33 | from sqlalchemy.orm import joinedload |
178 | 35 | from sqlalchemy.orm import joinedload_all | 34 | from sqlalchemy.orm import joinedload_all |
179 | 36 | from sqlalchemy.sql import exists | ||
180 | 37 | from sqlalchemy.sql import func | 35 | from sqlalchemy.sql import func |
181 | 38 | from sqlalchemy.sql.expression import literal_column | 36 | from sqlalchemy.sql.expression import literal_column |
182 | 39 | 37 | ||
183 | @@ -672,7 +670,7 @@ | |||
184 | 672 | 670 | ||
185 | 673 | 671 | ||
186 | 674 | @require_admin_context | 672 | @require_admin_context |
188 | 675 | def fixed_ip_associate_pool(context, network_id, instance_id): | 673 | def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None): |
189 | 676 | session = get_session() | 674 | session = get_session() |
190 | 677 | with session.begin(): | 675 | with session.begin(): |
191 | 678 | network_or_none = or_(models.FixedIp.network_id == network_id, | 676 | network_or_none = or_(models.FixedIp.network_id == network_id, |
192 | @@ -682,6 +680,7 @@ | |||
193 | 682 | filter_by(reserved=False).\ | 680 | filter_by(reserved=False).\ |
194 | 683 | filter_by(deleted=False).\ | 681 | filter_by(deleted=False).\ |
195 | 684 | filter_by(instance=None).\ | 682 | filter_by(instance=None).\ |
196 | 683 | filter_by(host=None).\ | ||
197 | 685 | with_lockmode('update').\ | 684 | with_lockmode('update').\ |
198 | 686 | first() | 685 | first() |
199 | 687 | # NOTE(vish): if with_lockmode isn't supported, as in sqlite, | 686 | # NOTE(vish): if with_lockmode isn't supported, as in sqlite, |
200 | @@ -692,9 +691,12 @@ | |||
201 | 692 | fixed_ip_ref.network = network_get(context, | 691 | fixed_ip_ref.network = network_get(context, |
202 | 693 | network_id, | 692 | network_id, |
203 | 694 | session=session) | 693 | session=session) |
207 | 695 | fixed_ip_ref.instance = instance_get(context, | 694 | if instance_id: |
208 | 696 | instance_id, | 695 | fixed_ip_ref.instance = instance_get(context, |
209 | 697 | session=session) | 696 | instance_id, |
210 | 697 | session=session) | ||
211 | 698 | if host: | ||
212 | 699 | fixed_ip_ref.host = host | ||
213 | 698 | session.add(fixed_ip_ref) | 700 | session.add(fixed_ip_ref) |
214 | 699 | return fixed_ip_ref['address'] | 701 | return fixed_ip_ref['address'] |
215 | 700 | 702 | ||
216 | @@ -750,7 +752,7 @@ | |||
217 | 750 | 752 | ||
218 | 751 | 753 | ||
219 | 752 | @require_admin_context | 754 | @require_admin_context |
221 | 753 | def fixed_ip_get_all_by_host(context, host=None): | 755 | def fixed_ip_get_all_by_instance_host(context, host=None): |
222 | 754 | session = get_session() | 756 | session = get_session() |
223 | 755 | 757 | ||
224 | 756 | result = session.query(models.FixedIp).\ | 758 | result = session.query(models.FixedIp).\ |
225 | @@ -800,6 +802,20 @@ | |||
226 | 800 | 802 | ||
227 | 801 | 803 | ||
228 | 802 | @require_context | 804 | @require_context |
229 | 805 | def fixed_ip_get_by_network_host(context, network_id, host): | ||
230 | 806 | session = get_session() | ||
231 | 807 | rv = session.query(models.FixedIp).\ | ||
232 | 808 | filter_by(network_id=network_id).\ | ||
233 | 809 | filter_by(host=host).\ | ||
234 | 810 | filter_by(deleted=False).\ | ||
235 | 811 | first() | ||
236 | 812 | if not rv: | ||
237 | 813 | raise exception.FixedIpNotFoundForNetworkHost(network_id=network_id, | ||
238 | 814 | host=host) | ||
239 | 815 | return rv | ||
240 | 816 | |||
241 | 817 | |||
242 | 818 | @require_context | ||
243 | 803 | def fixed_ip_get_by_virtual_interface(context, vif_id): | 819 | def fixed_ip_get_by_virtual_interface(context, vif_id): |
244 | 804 | session = get_session() | 820 | session = get_session() |
245 | 805 | rv = session.query(models.FixedIp).\ | 821 | rv = session.query(models.FixedIp).\ |
246 | @@ -1480,8 +1496,6 @@ | |||
247 | 1480 | called by project_get_networks under certain conditions | 1496 | called by project_get_networks under certain conditions |
248 | 1481 | and network manager add_network_to_project() | 1497 | and network manager add_network_to_project() |
249 | 1482 | 1498 | ||
250 | 1483 | only associates projects with networks that have configured hosts | ||
251 | 1484 | |||
252 | 1485 | only associate if the project doesn't already have a network | 1499 | only associate if the project doesn't already have a network |
253 | 1486 | or if force is True | 1500 | or if force is True |
254 | 1487 | 1501 | ||
255 | @@ -1497,7 +1511,6 @@ | |||
256 | 1497 | def network_query(project_filter): | 1511 | def network_query(project_filter): |
257 | 1498 | return session.query(models.Network).\ | 1512 | return session.query(models.Network).\ |
258 | 1499 | filter_by(deleted=False).\ | 1513 | filter_by(deleted=False).\ |
259 | 1500 | filter(models.Network.host != None).\ | ||
260 | 1501 | filter_by(project_id=project_filter).\ | 1514 | filter_by(project_id=project_filter).\ |
261 | 1502 | with_lockmode('update').\ | 1515 | with_lockmode('update').\ |
262 | 1503 | first() | 1516 | first() |
263 | @@ -1704,9 +1717,16 @@ | |||
264 | 1704 | def network_get_all_by_host(context, host): | 1717 | def network_get_all_by_host(context, host): |
265 | 1705 | session = get_session() | 1718 | session = get_session() |
266 | 1706 | with session.begin(): | 1719 | with session.begin(): |
267 | 1720 | # NOTE(vish): return networks that have host set | ||
268 | 1721 | # or that have a fixed ip with host set | ||
269 | 1722 | host_filter = or_(models.Network.host == host, | ||
270 | 1723 | models.FixedIp.host == host) | ||
271 | 1724 | |||
272 | 1707 | return session.query(models.Network).\ | 1725 | return session.query(models.Network).\ |
273 | 1708 | filter_by(deleted=False).\ | 1726 | filter_by(deleted=False).\ |
275 | 1709 | filter_by(host=host).\ | 1727 | join(models.Network.fixed_ips).\ |
276 | 1728 | filter(host_filter).\ | ||
277 | 1729 | filter_by(deleted=False).\ | ||
278 | 1710 | all() | 1730 | all() |
279 | 1711 | 1731 | ||
280 | 1712 | 1732 | ||
281 | @@ -1738,6 +1758,7 @@ | |||
282 | 1738 | network_ref = network_get(context, network_id, session=session) | 1758 | network_ref = network_get(context, network_id, session=session) |
283 | 1739 | network_ref.update(values) | 1759 | network_ref.update(values) |
284 | 1740 | network_ref.save(session=session) | 1760 | network_ref.save(session=session) |
285 | 1761 | return network_ref | ||
286 | 1741 | 1762 | ||
287 | 1742 | 1763 | ||
288 | 1743 | ################### | 1764 | ################### |
289 | 1744 | 1765 | ||
290 | === added file 'nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py' | |||
291 | --- nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py 1970-01-01 00:00:00 +0000 | |||
292 | +++ nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py 2011-07-20 18:28:31 +0000 | |||
293 | @@ -0,0 +1,44 @@ | |||
294 | 1 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 | ||
295 | 2 | |||
296 | 3 | # Copyright (c) 2011 OpenStack, LLC. | ||
297 | 4 | # All Rights Reserved. | ||
298 | 5 | # | ||
299 | 6 | # Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
300 | 7 | # not use this file except in compliance with the License. You may obtain | ||
301 | 8 | # a copy of the License at | ||
302 | 9 | # | ||
303 | 10 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
304 | 11 | # | ||
305 | 12 | # Unless required by applicable law or agreed to in writing, software | ||
306 | 13 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
307 | 14 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
308 | 15 | # License for the specific language governing permissions and limitations | ||
309 | 16 | # under the License. | ||
310 | 17 | |||
311 | 18 | from sqlalchemy import Column, Table, MetaData, Boolean, String | ||
312 | 19 | |||
313 | 20 | meta = MetaData() | ||
314 | 21 | |||
315 | 22 | fixed_ips_host = Column('host', String(255)) | ||
316 | 23 | |||
317 | 24 | networks_multi_host = Column('multi_host', Boolean, default=False) | ||
318 | 25 | |||
319 | 26 | |||
320 | 27 | def upgrade(migrate_engine): | ||
321 | 28 | meta.bind = migrate_engine | ||
322 | 29 | |||
323 | 30 | fixed_ips = Table('fixed_ips', meta, autoload=True) | ||
324 | 31 | fixed_ips.create_column(fixed_ips_host) | ||
325 | 32 | |||
326 | 33 | networks = Table('networks', meta, autoload=True) | ||
327 | 34 | networks.create_column(networks_multi_host) | ||
328 | 35 | |||
329 | 36 | |||
330 | 37 | def downgrade(migrate_engine): | ||
331 | 38 | meta.bind = migrate_engine | ||
332 | 39 | |||
333 | 40 | fixed_ips = Table('fixed_ips', meta, autoload=True) | ||
334 | 41 | fixed_ips.drop_column(fixed_ips_host) | ||
335 | 42 | |||
336 | 43 | networks = Table('networks', meta, autoload=True) | ||
337 | 44 | networks.drop_column(networks_multi_host) | ||
338 | 0 | 45 | ||
339 | === modified file 'nova/db/sqlalchemy/models.py' | |||
340 | --- nova/db/sqlalchemy/models.py 2011-07-08 03:07:58 +0000 | |||
341 | +++ nova/db/sqlalchemy/models.py 2011-07-20 18:28:31 +0000 | |||
342 | @@ -545,6 +545,7 @@ | |||
343 | 545 | injected = Column(Boolean, default=False) | 545 | injected = Column(Boolean, default=False) |
344 | 546 | cidr = Column(String(255), unique=True) | 546 | cidr = Column(String(255), unique=True) |
345 | 547 | cidr_v6 = Column(String(255), unique=True) | 547 | cidr_v6 = Column(String(255), unique=True) |
346 | 548 | multi_host = Column(Boolean, default=False) | ||
347 | 548 | 549 | ||
348 | 549 | gateway_v6 = Column(String(255)) | 550 | gateway_v6 = Column(String(255)) |
349 | 550 | netmask_v6 = Column(String(255)) | 551 | netmask_v6 = Column(String(255)) |
350 | @@ -603,6 +604,7 @@ | |||
351 | 603 | # leased means dhcp bridge has leased the ip | 604 | # leased means dhcp bridge has leased the ip |
352 | 604 | leased = Column(Boolean, default=False) | 605 | leased = Column(Boolean, default=False) |
353 | 605 | reserved = Column(Boolean, default=False) | 606 | reserved = Column(Boolean, default=False) |
354 | 607 | host = Column(String(255)) | ||
355 | 606 | 608 | ||
356 | 607 | 609 | ||
357 | 608 | class FloatingIp(BASE, NovaBase): | 610 | class FloatingIp(BASE, NovaBase): |
358 | 609 | 611 | ||
359 | === modified file 'nova/exception.py' | |||
360 | --- nova/exception.py 2011-07-13 18:19:32 +0000 | |||
361 | +++ nova/exception.py 2011-07-20 18:28:31 +0000 | |||
362 | @@ -408,6 +408,11 @@ | |||
363 | 408 | message = _("Instance %(instance_id)s has zero fixed ips.") | 408 | message = _("Instance %(instance_id)s has zero fixed ips.") |
364 | 409 | 409 | ||
365 | 410 | 410 | ||
366 | 411 | class FixedIpNotFoundForNetworkHost(FixedIpNotFound): | ||
367 | 412 | message = _("Network host %(host)s has zero fixed ips " | ||
368 | 413 | "in network %(network_id)s.") | ||
369 | 414 | |||
370 | 415 | |||
371 | 411 | class FixedIpNotFoundForSpecificInstance(FixedIpNotFound): | 416 | class FixedIpNotFoundForSpecificInstance(FixedIpNotFound): |
372 | 412 | message = _("Instance %(instance_id)s doesn't have fixed ip '%(ip)s'.") | 417 | message = _("Instance %(instance_id)s doesn't have fixed ip '%(ip)s'.") |
373 | 413 | 418 | ||
374 | 414 | 419 | ||
375 | === modified file 'nova/network/api.py' | |||
376 | --- nova/network/api.py 2011-07-19 20:49:05 +0000 | |||
377 | +++ nova/network/api.py 2011-07-20 18:28:31 +0000 | |||
378 | @@ -18,7 +18,6 @@ | |||
379 | 18 | 18 | ||
380 | 19 | """Handles all requests relating to instances (guest vms).""" | 19 | """Handles all requests relating to instances (guest vms).""" |
381 | 20 | 20 | ||
382 | 21 | from nova import db | ||
383 | 22 | from nova import exception | 21 | from nova import exception |
384 | 23 | from nova import flags | 22 | from nova import flags |
385 | 24 | from nova import log as logging | 23 | from nova import log as logging |
386 | @@ -108,7 +107,11 @@ | |||
387 | 108 | '(%(project)s)') % | 107 | '(%(project)s)') % |
388 | 109 | {'address': floating_ip['address'], | 108 | {'address': floating_ip['address'], |
389 | 110 | 'project': context.project_id}) | 109 | 'project': context.project_id}) |
391 | 111 | host = fixed_ip['network']['host'] | 110 | # NOTE(vish): if we are multi_host, send to the instances host |
392 | 111 | if fixed_ip['network']['multi_host']: | ||
393 | 112 | host = fixed_ip['instance']['host'] | ||
394 | 113 | else: | ||
395 | 114 | host = fixed_ip['network']['host'] | ||
396 | 112 | rpc.cast(context, | 115 | rpc.cast(context, |
397 | 113 | self.db.queue_get_for(context, FLAGS.network_topic, host), | 116 | self.db.queue_get_for(context, FLAGS.network_topic, host), |
398 | 114 | {'method': 'associate_floating_ip', | 117 | {'method': 'associate_floating_ip', |
399 | @@ -123,7 +126,11 @@ | |||
400 | 123 | return | 126 | return |
401 | 124 | if not floating_ip.get('fixed_ip'): | 127 | if not floating_ip.get('fixed_ip'): |
402 | 125 | raise exception.ApiError('Address is not associated.') | 128 | raise exception.ApiError('Address is not associated.') |
404 | 126 | host = floating_ip['fixed_ip']['network']['host'] | 129 | # NOTE(vish): if we are multi_host, send to the instances host |
405 | 130 | if floating_ip['fixed_ip']['network']['multi_host']: | ||
406 | 131 | host = floating_ip['fixed_ip']['instance']['host'] | ||
407 | 132 | else: | ||
408 | 133 | host = floating_ip['fixed_ip']['network']['host'] | ||
409 | 127 | rpc.call(context, | 134 | rpc.call(context, |
410 | 128 | self.db.queue_get_for(context, FLAGS.network_topic, host), | 135 | self.db.queue_get_for(context, FLAGS.network_topic, host), |
411 | 129 | {'method': 'disassociate_floating_ip', | 136 | {'method': 'disassociate_floating_ip', |
412 | @@ -137,7 +144,9 @@ | |||
413 | 137 | args = kwargs | 144 | args = kwargs |
414 | 138 | args['instance_id'] = instance['id'] | 145 | args['instance_id'] = instance['id'] |
415 | 139 | args['project_id'] = instance['project_id'] | 146 | args['project_id'] = instance['project_id'] |
416 | 147 | args['host'] = instance['host'] | ||
417 | 140 | args['instance_type_id'] = instance['instance_type_id'] | 148 | args['instance_type_id'] = instance['instance_type_id'] |
418 | 149 | |||
419 | 141 | return rpc.call(context, FLAGS.network_topic, | 150 | return rpc.call(context, FLAGS.network_topic, |
420 | 142 | {'method': 'allocate_for_instance', | 151 | {'method': 'allocate_for_instance', |
421 | 143 | 'args': args}) | 152 | 'args': args}) |
422 | @@ -176,7 +185,8 @@ | |||
423 | 176 | def get_instance_nw_info(self, context, instance): | 185 | def get_instance_nw_info(self, context, instance): |
424 | 177 | """Returns all network info related to an instance.""" | 186 | """Returns all network info related to an instance.""" |
425 | 178 | args = {'instance_id': instance['id'], | 187 | args = {'instance_id': instance['id'], |
427 | 179 | 'instance_type_id': instance['instance_type_id']} | 188 | 'instance_type_id': instance['instance_type_id'], |
428 | 189 | 'host': instance['host']} | ||
429 | 180 | return rpc.call(context, FLAGS.network_topic, | 190 | return rpc.call(context, FLAGS.network_topic, |
430 | 181 | {'method': 'get_instance_nw_info', | 191 | {'method': 'get_instance_nw_info', |
431 | 182 | 'args': args}) | 192 | 'args': args}) |
432 | 183 | 193 | ||
433 | === modified file 'nova/network/linux_net.py' | |||
434 | --- nova/network/linux_net.py 2011-06-27 21:48:03 +0000 | |||
435 | +++ nova/network/linux_net.py 2011-07-20 18:28:31 +0000 | |||
436 | @@ -497,7 +497,7 @@ | |||
437 | 497 | suffix = net_attrs['cidr'].rpartition('/')[2] | 497 | suffix = net_attrs['cidr'].rpartition('/')[2] |
438 | 498 | out, err = _execute('sudo', 'ip', 'addr', 'add', | 498 | out, err = _execute('sudo', 'ip', 'addr', 'add', |
439 | 499 | '%s/%s' % | 499 | '%s/%s' % |
441 | 500 | (net_attrs['gateway'], suffix), | 500 | (net_attrs['dhcp_server'], suffix), |
442 | 501 | 'brd', | 501 | 'brd', |
443 | 502 | net_attrs['broadcast'], | 502 | net_attrs['broadcast'], |
444 | 503 | 'dev', | 503 | 'dev', |
445 | @@ -551,21 +551,27 @@ | |||
446 | 551 | bridge) | 551 | bridge) |
447 | 552 | 552 | ||
448 | 553 | 553 | ||
450 | 554 | def get_dhcp_leases(context, network_id): | 554 | def get_dhcp_leases(context, network_ref): |
451 | 555 | """Return a network's hosts config in dnsmasq leasefile format.""" | 555 | """Return a network's hosts config in dnsmasq leasefile format.""" |
452 | 556 | hosts = [] | 556 | hosts = [] |
456 | 557 | for fixed_ip_ref in db.network_get_associated_fixed_ips(context, | 557 | for fixed_ref in db.network_get_associated_fixed_ips(context, |
457 | 558 | network_id): | 558 | network_ref['id']): |
458 | 559 | hosts.append(_host_lease(fixed_ip_ref)) | 559 | host = fixed_ref['instance']['host'] |
459 | 560 | if network_ref['multi_host'] and FLAGS.host != host: | ||
460 | 561 | continue | ||
461 | 562 | hosts.append(_host_lease(fixed_ref)) | ||
462 | 560 | return '\n'.join(hosts) | 563 | return '\n'.join(hosts) |
463 | 561 | 564 | ||
464 | 562 | 565 | ||
466 | 563 | def get_dhcp_hosts(context, network_id): | 566 | def get_dhcp_hosts(context, network_ref): |
467 | 564 | """Get network's hosts config in dhcp-host format.""" | 567 | """Get network's hosts config in dhcp-host format.""" |
468 | 565 | hosts = [] | 568 | hosts = [] |
472 | 566 | for fixed_ip_ref in db.network_get_associated_fixed_ips(context, | 569 | for fixed_ref in db.network_get_associated_fixed_ips(context, |
473 | 567 | network_id): | 570 | network_ref['id']): |
474 | 568 | hosts.append(_host_dhcp(fixed_ip_ref)) | 571 | host = fixed_ref['instance']['host'] |
475 | 572 | if network_ref['multi_host'] and FLAGS.host != host: | ||
476 | 573 | continue | ||
477 | 574 | hosts.append(_host_dhcp(fixed_ref)) | ||
478 | 569 | return '\n'.join(hosts) | 575 | return '\n'.join(hosts) |
479 | 570 | 576 | ||
480 | 571 | 577 | ||
481 | @@ -573,18 +579,16 @@ | |||
482 | 573 | # configuration options (like dchp-range, vlan, ...) | 579 | # configuration options (like dchp-range, vlan, ...) |
483 | 574 | # aren't reloaded. | 580 | # aren't reloaded. |
484 | 575 | @utils.synchronized('dnsmasq_start') | 581 | @utils.synchronized('dnsmasq_start') |
486 | 576 | def update_dhcp(context, network_id): | 582 | def update_dhcp(context, network_ref): |
487 | 577 | """(Re)starts a dnsmasq server for a given network. | 583 | """(Re)starts a dnsmasq server for a given network. |
488 | 578 | 584 | ||
489 | 579 | If a dnsmasq instance is already running then send a HUP | 585 | If a dnsmasq instance is already running then send a HUP |
490 | 580 | signal causing it to reload, otherwise spawn a new instance. | 586 | signal causing it to reload, otherwise spawn a new instance. |
491 | 581 | 587 | ||
492 | 582 | """ | 588 | """ |
493 | 583 | network_ref = db.network_get(context, network_id) | ||
494 | 584 | |||
495 | 585 | conffile = _dhcp_file(network_ref['bridge'], 'conf') | 589 | conffile = _dhcp_file(network_ref['bridge'], 'conf') |
496 | 586 | with open(conffile, 'w') as f: | 590 | with open(conffile, 'w') as f: |
498 | 587 | f.write(get_dhcp_hosts(context, network_id)) | 591 | f.write(get_dhcp_hosts(context, network_ref)) |
499 | 588 | 592 | ||
500 | 589 | # Make sure dnsmasq can actually read it (it setuid()s to "nobody") | 593 | # Make sure dnsmasq can actually read it (it setuid()s to "nobody") |
501 | 590 | os.chmod(conffile, 0644) | 594 | os.chmod(conffile, 0644) |
502 | @@ -612,9 +616,7 @@ | |||
503 | 612 | 616 | ||
504 | 613 | 617 | ||
505 | 614 | @utils.synchronized('radvd_start') | 618 | @utils.synchronized('radvd_start') |
509 | 615 | def update_ra(context, network_id): | 619 | def update_ra(context, network_ref): |
507 | 616 | network_ref = db.network_get(context, network_id) | ||
508 | 617 | |||
510 | 618 | conffile = _ra_file(network_ref['bridge'], 'conf') | 620 | conffile = _ra_file(network_ref['bridge'], 'conf') |
511 | 619 | with open(conffile, 'w') as f: | 621 | with open(conffile, 'w') as f: |
512 | 620 | conf_str = """ | 622 | conf_str = """ |
513 | @@ -650,9 +652,6 @@ | |||
514 | 650 | LOG.debug(_('Pid %d is stale, relaunching radvd'), pid) | 652 | LOG.debug(_('Pid %d is stale, relaunching radvd'), pid) |
515 | 651 | command = _ra_cmd(network_ref) | 653 | command = _ra_cmd(network_ref) |
516 | 652 | _execute(*command) | 654 | _execute(*command) |
517 | 653 | db.network_update(context, network_id, | ||
518 | 654 | {'gateway_v6': | ||
519 | 655 | utils.get_my_linklocal(network_ref['bridge'])}) | ||
520 | 656 | 655 | ||
521 | 657 | 656 | ||
522 | 658 | def _host_lease(fixed_ip_ref): | 657 | def _host_lease(fixed_ip_ref): |
523 | @@ -701,10 +700,11 @@ | |||
524 | 701 | cmd = ['sudo', '-E', 'dnsmasq', | 700 | cmd = ['sudo', '-E', 'dnsmasq', |
525 | 702 | '--strict-order', | 701 | '--strict-order', |
526 | 703 | '--bind-interfaces', | 702 | '--bind-interfaces', |
527 | 703 | '--interface=%s' % net['bridge'], | ||
528 | 704 | '--conf-file=%s' % FLAGS.dnsmasq_config_file, | 704 | '--conf-file=%s' % FLAGS.dnsmasq_config_file, |
529 | 705 | '--domain=%s' % FLAGS.dhcp_domain, | 705 | '--domain=%s' % FLAGS.dhcp_domain, |
530 | 706 | '--pid-file=%s' % _dhcp_file(net['bridge'], 'pid'), | 706 | '--pid-file=%s' % _dhcp_file(net['bridge'], 'pid'), |
532 | 707 | '--listen-address=%s' % net['gateway'], | 707 | '--listen-address=%s' % net['dhcp_server'], |
533 | 708 | '--except-interface=lo', | 708 | '--except-interface=lo', |
534 | 709 | '--dhcp-range=%s,static,120s' % net['dhcp_start'], | 709 | '--dhcp-range=%s,static,120s' % net['dhcp_start'], |
535 | 710 | '--dhcp-lease-max=%s' % len(netaddr.IPNetwork(net['cidr'])), | 710 | '--dhcp-lease-max=%s' % len(netaddr.IPNetwork(net['cidr'])), |
536 | 711 | 711 | ||
537 | === modified file 'nova/network/manager.py' | |||
538 | --- nova/network/manager.py 2011-07-19 19:29:44 +0000 | |||
539 | +++ nova/network/manager.py 2011-07-20 18:28:31 +0000 | |||
540 | @@ -28,7 +28,6 @@ | |||
541 | 28 | :flat_network_bridge: Bridge device for simple network instances | 28 | :flat_network_bridge: Bridge device for simple network instances |
542 | 29 | :flat_interface: FlatDhcp will bridge into this interface if set | 29 | :flat_interface: FlatDhcp will bridge into this interface if set |
543 | 30 | :flat_network_dns: Dns for simple network | 30 | :flat_network_dns: Dns for simple network |
544 | 31 | :flat_network_dhcp_start: Dhcp start for FlatDhcp | ||
545 | 32 | :vlan_start: First VLAN for private networks | 31 | :vlan_start: First VLAN for private networks |
546 | 33 | :vpn_ip: Public IP for the cloudpipe VPN servers | 32 | :vpn_ip: Public IP for the cloudpipe VPN servers |
547 | 34 | :vpn_start: First Vpn port for private networks | 33 | :vpn_start: First Vpn port for private networks |
548 | @@ -49,7 +48,6 @@ | |||
549 | 49 | import math | 48 | import math |
550 | 50 | import netaddr | 49 | import netaddr |
551 | 51 | import socket | 50 | import socket |
552 | 52 | import pickle | ||
553 | 53 | from eventlet import greenpool | 51 | from eventlet import greenpool |
554 | 54 | 52 | ||
555 | 55 | from nova import context | 53 | from nova import context |
556 | @@ -78,8 +76,6 @@ | |||
557 | 78 | 'Whether to attempt to inject network setup into guest') | 76 | 'Whether to attempt to inject network setup into guest') |
558 | 79 | flags.DEFINE_string('flat_interface', None, | 77 | flags.DEFINE_string('flat_interface', None, |
559 | 80 | 'FlatDhcp will bridge into this interface if set') | 78 | 'FlatDhcp will bridge into this interface if set') |
560 | 81 | flags.DEFINE_string('flat_network_dhcp_start', '10.0.0.2', | ||
561 | 82 | 'Dhcp start for FlatDhcp') | ||
562 | 83 | flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks') | 79 | flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks') |
563 | 84 | flags.DEFINE_string('vlan_interface', None, | 80 | flags.DEFINE_string('vlan_interface', None, |
564 | 85 | 'vlans will bridge into this interface if set') | 81 | 'vlans will bridge into this interface if set') |
565 | @@ -87,6 +83,8 @@ | |||
566 | 87 | flags.DEFINE_string('vpn_ip', '$my_ip', | 83 | flags.DEFINE_string('vpn_ip', '$my_ip', |
567 | 88 | 'Public IP for the cloudpipe VPN servers') | 84 | 'Public IP for the cloudpipe VPN servers') |
568 | 89 | flags.DEFINE_integer('vpn_start', 1000, 'First Vpn port for private networks') | 85 | flags.DEFINE_integer('vpn_start', 1000, 'First Vpn port for private networks') |
569 | 86 | flags.DEFINE_bool('multi_host', False, | ||
570 | 87 | 'Default value for multi_host in networks') | ||
571 | 90 | flags.DEFINE_integer('network_size', 256, | 88 | flags.DEFINE_integer('network_size', 256, |
572 | 91 | 'Number of addresses in each private subnet') | 89 | 'Number of addresses in each private subnet') |
573 | 92 | flags.DEFINE_string('floating_range', '4.4.4.0/24', | 90 | flags.DEFINE_string('floating_range', '4.4.4.0/24', |
574 | @@ -104,7 +102,8 @@ | |||
575 | 104 | 'Seconds after which a deallocated ip is disassociated') | 102 | 'Seconds after which a deallocated ip is disassociated') |
576 | 105 | flags.DEFINE_integer('create_unique_mac_address_attempts', 5, | 103 | flags.DEFINE_integer('create_unique_mac_address_attempts', 5, |
577 | 106 | 'Number of attempts to create unique mac address') | 104 | 'Number of attempts to create unique mac address') |
579 | 107 | 105 | flags.DEFINE_bool('auto_assign_floating_ip', False, | |
580 | 106 | 'Autoassigning floating ip to VM') | ||
581 | 108 | flags.DEFINE_bool('use_ipv6', False, | 107 | flags.DEFINE_bool('use_ipv6', False, |
582 | 109 | 'use the ipv6') | 108 | 'use the ipv6') |
583 | 110 | flags.DEFINE_string('network_host', socket.gethostname(), | 109 | flags.DEFINE_string('network_host', socket.gethostname(), |
584 | @@ -124,16 +123,26 @@ | |||
585 | 124 | used since they share code to RPC.call allocate_fixed_ip on the | 123 | used since they share code to RPC.call allocate_fixed_ip on the |
586 | 125 | correct network host to configure dnsmasq | 124 | correct network host to configure dnsmasq |
587 | 126 | """ | 125 | """ |
589 | 127 | def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs): | 126 | def _allocate_fixed_ips(self, context, instance_id, host, networks, |
590 | 127 | **kwargs): | ||
591 | 128 | """Calls allocate_fixed_ip once for each network.""" | 128 | """Calls allocate_fixed_ip once for each network.""" |
592 | 129 | green_pool = greenpool.GreenPool() | 129 | green_pool = greenpool.GreenPool() |
593 | 130 | 130 | ||
594 | 131 | vpn = kwargs.pop('vpn') | 131 | vpn = kwargs.pop('vpn') |
595 | 132 | for network in networks: | 132 | for network in networks: |
597 | 133 | if network['host'] != self.host: | 133 | # NOTE(vish): if we are not multi_host pass to the network host |
598 | 134 | if not network['multi_host']: | ||
599 | 135 | host = network['host'] | ||
600 | 136 | # NOTE(vish): if there is no network host, set one | ||
601 | 137 | if host == None: | ||
602 | 138 | host = rpc.call(context, FLAGS.network_topic, | ||
603 | 139 | {'method': 'set_network_host', | ||
604 | 140 | 'args': {'network_ref': network}}) | ||
605 | 141 | if host != self.host: | ||
606 | 134 | # need to call allocate_fixed_ip to correct network host | 142 | # need to call allocate_fixed_ip to correct network host |
609 | 135 | topic = self.db.queue_get_for(context, FLAGS.network_topic, | 143 | topic = self.db.queue_get_for(context, |
610 | 136 | network['host']) | 144 | FLAGS.network_topic, |
611 | 145 | host) | ||
612 | 137 | args = {} | 146 | args = {} |
613 | 138 | args['instance_id'] = instance_id | 147 | args['instance_id'] = instance_id |
614 | 139 | args['network_id'] = network['id'] | 148 | args['network_id'] = network['id'] |
615 | @@ -149,12 +158,13 @@ | |||
616 | 149 | # wait for all of the allocates (if any) to finish | 158 | # wait for all of the allocates (if any) to finish |
617 | 150 | green_pool.waitall() | 159 | green_pool.waitall() |
618 | 151 | 160 | ||
620 | 152 | def _rpc_allocate_fixed_ip(self, context, instance_id, network_id): | 161 | def _rpc_allocate_fixed_ip(self, context, instance_id, network_id, |
621 | 162 | **kwargs): | ||
622 | 153 | """Sits in between _allocate_fixed_ips and allocate_fixed_ip to | 163 | """Sits in between _allocate_fixed_ips and allocate_fixed_ip to |
623 | 154 | perform network lookup on the far side of rpc. | 164 | perform network lookup on the far side of rpc. |
624 | 155 | """ | 165 | """ |
625 | 156 | network = self.db.network_get(context, network_id) | 166 | network = self.db.network_get(context, network_id) |
627 | 157 | self.allocate_fixed_ip(context, instance_id, network) | 167 | self.allocate_fixed_ip(context, instance_id, network, **kwargs) |
628 | 158 | 168 | ||
629 | 159 | 169 | ||
630 | 160 | class FloatingIP(object): | 170 | class FloatingIP(object): |
631 | @@ -193,7 +203,7 @@ | |||
632 | 193 | # which is currently the NetworkManager version | 203 | # which is currently the NetworkManager version |
633 | 194 | # do this first so fixed ip is already allocated | 204 | # do this first so fixed ip is already allocated |
634 | 195 | ips = super(FloatingIP, self).allocate_for_instance(context, **kwargs) | 205 | ips = super(FloatingIP, self).allocate_for_instance(context, **kwargs) |
636 | 196 | if hasattr(FLAGS, 'auto_assign_floating_ip'): | 206 | if FLAGS.auto_assign_floating_ip: |
637 | 197 | # allocate a floating ip (public_ip is just the address string) | 207 | # allocate a floating ip (public_ip is just the address string) |
638 | 198 | public_ip = self.allocate_floating_ip(context, project_id) | 208 | public_ip = self.allocate_floating_ip(context, project_id) |
639 | 199 | # set auto_assigned column to true for the floating ip | 209 | # set auto_assigned column to true for the floating ip |
640 | @@ -300,15 +310,36 @@ | |||
641 | 300 | super(NetworkManager, self).__init__(service_name='network', | 310 | super(NetworkManager, self).__init__(service_name='network', |
642 | 301 | *args, **kwargs) | 311 | *args, **kwargs) |
643 | 302 | 312 | ||
644 | 313 | @utils.synchronized('get_dhcp') | ||
645 | 314 | def _get_dhcp_ip(self, context, network_ref, host=None): | ||
646 | 315 | """Get the proper dhcp address to listen on.""" | ||
647 | 316 | # NOTE(vish): this is for compatibility | ||
648 | 317 | if not network_ref['multi_host']: | ||
649 | 318 | return network_ref['gateway'] | ||
650 | 319 | |||
651 | 320 | if not host: | ||
652 | 321 | host = self.host | ||
653 | 322 | network_id = network_ref['id'] | ||
654 | 323 | try: | ||
655 | 324 | fip = self.db.fixed_ip_get_by_network_host(context, | ||
656 | 325 | network_id, | ||
657 | 326 | host) | ||
658 | 327 | return fip['address'] | ||
659 | 328 | except exception.FixedIpNotFoundForNetworkHost: | ||
660 | 329 | elevated = context.elevated() | ||
661 | 330 | return self.db.fixed_ip_associate_pool(elevated, | ||
662 | 331 | network_id, | ||
663 | 332 | host=host) | ||
664 | 333 | |||
665 | 303 | def init_host(self): | 334 | def init_host(self): |
666 | 304 | """Do any initialization that needs to be run if this is a | 335 | """Do any initialization that needs to be run if this is a |
667 | 305 | standalone service. | 336 | standalone service. |
668 | 306 | """ | 337 | """ |
671 | 307 | # Set up this host for networks in which it's already | 338 | # NOTE(vish): Set up networks for which this host already has |
672 | 308 | # the designated network host. | 339 | # an ip address. |
673 | 309 | ctxt = context.get_admin_context() | 340 | ctxt = context.get_admin_context() |
674 | 310 | for network in self.db.network_get_all_by_host(ctxt, self.host): | 341 | for network in self.db.network_get_all_by_host(ctxt, self.host): |
676 | 311 | self._on_set_network_host(ctxt, network['id']) | 342 | self._setup_network(ctxt, network) |
677 | 312 | 343 | ||
678 | 313 | def periodic_tasks(self, context=None): | 344 | def periodic_tasks(self, context=None): |
679 | 314 | """Tasks to be run at a periodic interval.""" | 345 | """Tasks to be run at a periodic interval.""" |
680 | @@ -323,32 +354,13 @@ | |||
681 | 323 | if num: | 354 | if num: |
682 | 324 | LOG.debug(_('Dissassociated %s stale fixed ip(s)'), num) | 355 | LOG.debug(_('Dissassociated %s stale fixed ip(s)'), num) |
683 | 325 | 356 | ||
688 | 326 | # setup any new networks which have been created | 357 | def set_network_host(self, context, network_ref): |
685 | 327 | self.set_network_hosts(context) | ||
686 | 328 | |||
687 | 329 | def set_network_host(self, context, network_id): | ||
689 | 330 | """Safely sets the host of the network.""" | 358 | """Safely sets the host of the network.""" |
690 | 331 | LOG.debug(_('setting network host'), context=context) | 359 | LOG.debug(_('setting network host'), context=context) |
691 | 332 | host = self.db.network_set_host(context, | 360 | host = self.db.network_set_host(context, |
693 | 333 | network_id, | 361 | network_ref['id'], |
694 | 334 | self.host) | 362 | self.host) |
712 | 335 | if host == self.host: | 363 | return host |
696 | 336 | self._on_set_network_host(context, network_id) | ||
697 | 337 | |||
698 | 338 | def set_network_hosts(self, context): | ||
699 | 339 | """Set the network hosts for any networks which are unset.""" | ||
700 | 340 | try: | ||
701 | 341 | networks = self.db.network_get_all(context) | ||
702 | 342 | except exception.NoNetworksFound: | ||
703 | 343 | # no networks found, nothing to do | ||
704 | 344 | return | ||
705 | 345 | |||
706 | 346 | for network in networks: | ||
707 | 347 | host = network['host'] | ||
708 | 348 | if not host: | ||
709 | 349 | # break so worker will only grab 1 (to help scale flatter) | ||
710 | 350 | self.set_network_host(context, network['id']) | ||
711 | 351 | break | ||
713 | 352 | 364 | ||
714 | 353 | def _get_networks_for_instance(self, context, instance_id, project_id): | 365 | def _get_networks_for_instance(self, context, instance_id, project_id): |
715 | 354 | """Determine & return which networks an instance should connect to.""" | 366 | """Determine & return which networks an instance should connect to.""" |
716 | @@ -361,9 +373,9 @@ | |||
717 | 361 | # we don't care if no networks are found | 373 | # we don't care if no networks are found |
718 | 362 | pass | 374 | pass |
719 | 363 | 375 | ||
721 | 364 | # return only networks which are not vlan networks and have host set | 376 | # return only networks which are not vlan networks |
722 | 365 | return [network for network in networks if | 377 | return [network for network in networks if |
724 | 366 | not network['vlan'] and network['host']] | 378 | not network['vlan']] |
725 | 367 | 379 | ||
726 | 368 | def allocate_for_instance(self, context, **kwargs): | 380 | def allocate_for_instance(self, context, **kwargs): |
727 | 369 | """Handles allocating the various network resources for an instance. | 381 | """Handles allocating the various network resources for an instance. |
728 | @@ -371,6 +383,7 @@ | |||
729 | 371 | rpc.called by network_api | 383 | rpc.called by network_api |
730 | 372 | """ | 384 | """ |
731 | 373 | instance_id = kwargs.pop('instance_id') | 385 | instance_id = kwargs.pop('instance_id') |
732 | 386 | host = kwargs.pop('host') | ||
733 | 374 | project_id = kwargs.pop('project_id') | 387 | project_id = kwargs.pop('project_id') |
734 | 375 | type_id = kwargs.pop('instance_type_id') | 388 | type_id = kwargs.pop('instance_type_id') |
735 | 376 | vpn = kwargs.pop('vpn') | 389 | vpn = kwargs.pop('vpn') |
736 | @@ -379,9 +392,11 @@ | |||
737 | 379 | context=context) | 392 | context=context) |
738 | 380 | networks = self._get_networks_for_instance(admin_context, instance_id, | 393 | networks = self._get_networks_for_instance(admin_context, instance_id, |
739 | 381 | project_id) | 394 | project_id) |
740 | 395 | LOG.warn(networks) | ||
741 | 382 | self._allocate_mac_addresses(context, instance_id, networks) | 396 | self._allocate_mac_addresses(context, instance_id, networks) |
744 | 383 | self._allocate_fixed_ips(admin_context, instance_id, networks, vpn=vpn) | 397 | self._allocate_fixed_ips(admin_context, instance_id, host, networks, |
745 | 384 | return self.get_instance_nw_info(context, instance_id, type_id) | 398 | vpn=vpn) |
746 | 399 | return self.get_instance_nw_info(context, instance_id, type_id, host) | ||
747 | 385 | 400 | ||
748 | 386 | def deallocate_for_instance(self, context, **kwargs): | 401 | def deallocate_for_instance(self, context, **kwargs): |
749 | 387 | """Handles deallocating various network resources for an instance. | 402 | """Handles deallocating various network resources for an instance. |
750 | @@ -401,7 +416,8 @@ | |||
751 | 401 | # deallocate vifs (mac addresses) | 416 | # deallocate vifs (mac addresses) |
752 | 402 | self.db.virtual_interface_delete_by_instance(context, instance_id) | 417 | self.db.virtual_interface_delete_by_instance(context, instance_id) |
753 | 403 | 418 | ||
755 | 404 | def get_instance_nw_info(self, context, instance_id, instance_type_id): | 419 | def get_instance_nw_info(self, context, instance_id, |
756 | 420 | instance_type_id, host): | ||
757 | 405 | """Creates network info list for instance. | 421 | """Creates network info list for instance. |
758 | 406 | 422 | ||
759 | 407 | called by allocate_for_instance and netowrk_api | 423 | called by allocate_for_instance and netowrk_api |
760 | @@ -445,9 +461,16 @@ | |||
761 | 445 | 'cidr': network['cidr'], | 461 | 'cidr': network['cidr'], |
762 | 446 | 'cidr_v6': network['cidr_v6'], | 462 | 'cidr_v6': network['cidr_v6'], |
763 | 447 | 'injected': network['injected']} | 463 | 'injected': network['injected']} |
764 | 464 | if network['multi_host']: | ||
765 | 465 | dhcp_server = self._get_dhcp_ip(context, network, host) | ||
766 | 466 | else: | ||
767 | 467 | dhcp_server = self._get_dhcp_ip(context, | ||
768 | 468 | network, | ||
769 | 469 | network['host']) | ||
770 | 448 | info = { | 470 | info = { |
771 | 449 | 'label': network['label'], | 471 | 'label': network['label'], |
772 | 450 | 'gateway': network['gateway'], | 472 | 'gateway': network['gateway'], |
773 | 473 | 'dhcp_server': dhcp_server, | ||
774 | 451 | 'broadcast': network['broadcast'], | 474 | 'broadcast': network['broadcast'], |
775 | 452 | 'mac': vif['address'], | 475 | 'mac': vif['address'], |
776 | 453 | 'rxtx_cap': flavor['rxtx_cap'], | 476 | 'rxtx_cap': flavor['rxtx_cap'], |
777 | @@ -487,10 +510,10 @@ | |||
778 | 487 | random.randint(0x00, 0xff)] | 510 | random.randint(0x00, 0xff)] |
779 | 488 | return ':'.join(map(lambda x: "%02x" % x, mac)) | 511 | return ':'.join(map(lambda x: "%02x" % x, mac)) |
780 | 489 | 512 | ||
782 | 490 | def add_fixed_ip_to_instance(self, context, instance_id, network_id): | 513 | def add_fixed_ip_to_instance(self, context, instance_id, host, network_id): |
783 | 491 | """Adds a fixed ip to an instance from specified network.""" | 514 | """Adds a fixed ip to an instance from specified network.""" |
784 | 492 | networks = [self.db.network_get(context, network_id)] | 515 | networks = [self.db.network_get(context, network_id)] |
786 | 493 | self._allocate_fixed_ips(context, instance_id, networks) | 516 | self._allocate_fixed_ips(context, instance_id, host, networks) |
787 | 494 | 517 | ||
788 | 495 | def remove_fixed_ip_from_instance(self, context, instance_id, address): | 518 | def remove_fixed_ip_from_instance(self, context, instance_id, address): |
789 | 496 | """Removes a fixed ip from an instance from specified network.""" | 519 | """Removes a fixed ip from an instance from specified network.""" |
790 | @@ -517,6 +540,7 @@ | |||
791 | 517 | values = {'allocated': True, | 540 | values = {'allocated': True, |
792 | 518 | 'virtual_interface_id': vif['id']} | 541 | 'virtual_interface_id': vif['id']} |
793 | 519 | self.db.fixed_ip_update(context, address, values) | 542 | self.db.fixed_ip_update(context, address, values) |
794 | 543 | self._setup_network(context, network) | ||
795 | 520 | return address | 544 | return address |
796 | 521 | 545 | ||
797 | 522 | def deallocate_fixed_ip(self, context, address, **kwargs): | 546 | def deallocate_fixed_ip(self, context, address, **kwargs): |
798 | @@ -562,10 +586,10 @@ | |||
799 | 562 | # means there will stale entries in the conf file | 586 | # means there will stale entries in the conf file |
800 | 563 | # the code below will update the file if necessary | 587 | # the code below will update the file if necessary |
801 | 564 | if FLAGS.update_dhcp_on_disassociate: | 588 | if FLAGS.update_dhcp_on_disassociate: |
804 | 565 | network = self.db.fixed_ip_get_network(context, address) | 589 | network_ref = self.db.fixed_ip_get_network(context, address) |
805 | 566 | self.driver.update_dhcp(context, network['id']) | 590 | self._setup_network(context, network_ref) |
806 | 567 | 591 | ||
808 | 568 | def create_networks(self, context, label, cidr, num_networks, | 592 | def create_networks(self, context, label, cidr, multi_host, num_networks, |
809 | 569 | network_size, cidr_v6, gateway_v6, bridge, | 593 | network_size, cidr_v6, gateway_v6, bridge, |
810 | 570 | bridge_interface, **kwargs): | 594 | bridge_interface, **kwargs): |
811 | 571 | """Create networks based on parameters.""" | 595 | """Create networks based on parameters.""" |
812 | @@ -584,6 +608,7 @@ | |||
813 | 584 | net['bridge_interface'] = bridge_interface | 608 | net['bridge_interface'] = bridge_interface |
814 | 585 | net['dns'] = FLAGS.flat_network_dns | 609 | net['dns'] = FLAGS.flat_network_dns |
815 | 586 | net['cidr'] = cidr | 610 | net['cidr'] = cidr |
816 | 611 | net['multi_host'] = multi_host | ||
817 | 587 | net['netmask'] = str(project_net.netmask) | 612 | net['netmask'] = str(project_net.netmask) |
818 | 588 | net['gateway'] = str(project_net[1]) | 613 | net['gateway'] = str(project_net[1]) |
819 | 589 | net['broadcast'] = str(project_net.broadcast) | 614 | net['broadcast'] = str(project_net.broadcast) |
820 | @@ -659,12 +684,13 @@ | |||
821 | 659 | 'address': address, | 684 | 'address': address, |
822 | 660 | 'reserved': reserved}) | 685 | 'reserved': reserved}) |
823 | 661 | 686 | ||
825 | 662 | def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs): | 687 | def _allocate_fixed_ips(self, context, instance_id, host, networks, |
826 | 688 | **kwargs): | ||
827 | 663 | """Calls allocate_fixed_ip once for each network.""" | 689 | """Calls allocate_fixed_ip once for each network.""" |
828 | 664 | raise NotImplementedError() | 690 | raise NotImplementedError() |
829 | 665 | 691 | ||
832 | 666 | def _on_set_network_host(self, context, network_id): | 692 | def _setup_network(self, context, network_ref): |
833 | 667 | """Called when this host becomes the host for a network.""" | 693 | """Sets up network on this host.""" |
834 | 668 | raise NotImplementedError() | 694 | raise NotImplementedError() |
835 | 669 | 695 | ||
836 | 670 | def setup_compute_network(self, context, instance_id): | 696 | def setup_compute_network(self, context, instance_id): |
837 | @@ -706,7 +732,8 @@ | |||
838 | 706 | 732 | ||
839 | 707 | timeout_fixed_ips = False | 733 | timeout_fixed_ips = False |
840 | 708 | 734 | ||
842 | 709 | def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs): | 735 | def _allocate_fixed_ips(self, context, instance_id, host, networks, |
843 | 736 | **kwargs): | ||
844 | 710 | """Calls allocate_fixed_ip once for each network.""" | 737 | """Calls allocate_fixed_ip once for each network.""" |
845 | 711 | for network in networks: | 738 | for network in networks: |
846 | 712 | self.allocate_fixed_ip(context, instance_id, network) | 739 | self.allocate_fixed_ip(context, instance_id, network) |
847 | @@ -724,12 +751,12 @@ | |||
848 | 724 | """ | 751 | """ |
849 | 725 | pass | 752 | pass |
850 | 726 | 753 | ||
853 | 727 | def _on_set_network_host(self, context, network_id): | 754 | def _setup_network(self, context, network_ref): |
854 | 728 | """Called when this host becomes the host for a network.""" | 755 | """Setup Network on this host.""" |
855 | 729 | net = {} | 756 | net = {} |
856 | 730 | net['injected'] = FLAGS.flat_injected | 757 | net['injected'] = FLAGS.flat_injected |
857 | 731 | net['dns'] = FLAGS.flat_network_dns | 758 | net['dns'] = FLAGS.flat_network_dns |
859 | 732 | self.db.network_update(context, network_id, net) | 759 | self.db.network_update(context, network_ref['id'], net) |
860 | 733 | 760 | ||
861 | 734 | 761 | ||
862 | 735 | class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): | 762 | class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): |
863 | @@ -760,30 +787,23 @@ | |||
864 | 760 | """ | 787 | """ |
865 | 761 | networks = db.network_get_all_by_instance(context, instance_id) | 788 | networks = db.network_get_all_by_instance(context, instance_id) |
866 | 762 | for network in networks: | 789 | for network in networks: |
889 | 763 | self.driver.ensure_bridge(network['bridge'], | 790 | if not network['multi_host']: |
890 | 764 | network['bridge_interface']) | 791 | self.driver.ensure_bridge(network['bridge'], |
891 | 765 | 792 | network['bridge_interface']) | |
892 | 766 | def allocate_fixed_ip(self, context, instance_id, network, **kwargs): | 793 | |
893 | 767 | """Allocate flat_network fixed_ip, then setup dhcp for this network.""" | 794 | def _setup_network(self, context, network_ref): |
894 | 768 | address = super(FlatDHCPManager, self).allocate_fixed_ip(context, | 795 | """Sets up network on this host.""" |
895 | 769 | instance_id, | 796 | network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) |
896 | 770 | network) | 797 | self.driver.ensure_bridge(network_ref['bridge'], |
897 | 771 | if not FLAGS.fake_network: | 798 | network_ref['bridge_interface'], |
898 | 772 | self.driver.update_dhcp(context, network['id']) | 799 | network_ref) |
899 | 773 | 800 | if not FLAGS.fake_network: | |
900 | 774 | def _on_set_network_host(self, context, network_id): | 801 | self.driver.update_dhcp(context, network_ref) |
879 | 775 | """Called when this host becomes the host for a project.""" | ||
880 | 776 | net = {} | ||
881 | 777 | net['dhcp_start'] = FLAGS.flat_network_dhcp_start | ||
882 | 778 | self.db.network_update(context, network_id, net) | ||
883 | 779 | network = db.network_get(context, network_id) | ||
884 | 780 | self.driver.ensure_bridge(network['bridge'], | ||
885 | 781 | network['bridge_interface'], | ||
886 | 782 | network) | ||
887 | 783 | if not FLAGS.fake_network: | ||
888 | 784 | self.driver.update_dhcp(context, network_id) | ||
901 | 785 | if(FLAGS.use_ipv6): | 802 | if(FLAGS.use_ipv6): |
903 | 786 | self.driver.update_ra(context, network_id) | 803 | self.driver.update_ra(context, network_ref) |
904 | 804 | gateway = utils.get_my_linklocal(network_ref['bridge']) | ||
905 | 805 | self.db.network_update(context, network_ref['id'], | ||
906 | 806 | {'gateway_v6': gateway}) | ||
907 | 787 | 807 | ||
908 | 788 | 808 | ||
909 | 789 | class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): | 809 | class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): |
910 | @@ -832,8 +852,8 @@ | |||
911 | 832 | values = {'allocated': True, | 852 | values = {'allocated': True, |
912 | 833 | 'virtual_interface_id': vif['id']} | 853 | 'virtual_interface_id': vif['id']} |
913 | 834 | self.db.fixed_ip_update(context, address, values) | 854 | self.db.fixed_ip_update(context, address, values) |
916 | 835 | if not FLAGS.fake_network: | 855 | self._setup_network(context, network) |
917 | 836 | self.driver.update_dhcp(context, network['id']) | 856 | return address |
918 | 837 | 857 | ||
919 | 838 | def add_network_to_project(self, context, project_id): | 858 | def add_network_to_project(self, context, project_id): |
920 | 839 | """Force adds another network to a project.""" | 859 | """Force adds another network to a project.""" |
921 | @@ -845,17 +865,15 @@ | |||
922 | 845 | """ | 865 | """ |
923 | 846 | networks = self.db.network_get_all_by_instance(context, instance_id) | 866 | networks = self.db.network_get_all_by_instance(context, instance_id) |
924 | 847 | for network in networks: | 867 | for network in networks: |
928 | 848 | self.driver.ensure_vlan_bridge(network['vlan'], | 868 | if not network['multi_host']: |
929 | 849 | network['bridge'], | 869 | self.driver.ensure_vlan_bridge(network['vlan'], |
930 | 850 | network['bridge_interface']) | 870 | network['bridge'], |
931 | 871 | network['bridge_interface']) | ||
932 | 851 | 872 | ||
933 | 852 | def _get_networks_for_instance(self, context, instance_id, project_id): | 873 | def _get_networks_for_instance(self, context, instance_id, project_id): |
934 | 853 | """Determine which networks an instance should connect to.""" | 874 | """Determine which networks an instance should connect to.""" |
935 | 854 | # get networks associated with project | 875 | # get networks associated with project |
940 | 855 | networks = self.db.project_get_networks(context, project_id) | 876 | return self.db.project_get_networks(context, project_id) |
937 | 856 | |||
938 | 857 | # return only networks which have host set | ||
939 | 858 | return [network for network in networks if network['host']] | ||
941 | 859 | 877 | ||
942 | 860 | def create_networks(self, context, **kwargs): | 878 | def create_networks(self, context, **kwargs): |
943 | 861 | """Create networks based on parameters.""" | 879 | """Create networks based on parameters.""" |
944 | @@ -874,32 +892,35 @@ | |||
945 | 874 | 892 | ||
946 | 875 | NetworkManager.create_networks(self, context, vpn=True, **kwargs) | 893 | NetworkManager.create_networks(self, context, vpn=True, **kwargs) |
947 | 876 | 894 | ||
952 | 877 | def _on_set_network_host(self, context, network_id): | 895 | def _setup_network(self, context, network_ref): |
953 | 878 | """Called when this host becomes the host for a network.""" | 896 | """Sets up network on this host.""" |
954 | 879 | network = self.db.network_get(context, network_id) | 897 | network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) |
955 | 880 | if not network['vpn_public_address']: | 898 | if not network_ref['vpn_public_address']: |
956 | 881 | net = {} | 899 | net = {} |
957 | 882 | address = FLAGS.vpn_ip | 900 | address = FLAGS.vpn_ip |
958 | 883 | net['vpn_public_address'] = address | 901 | net['vpn_public_address'] = address |
960 | 884 | db.network_update(context, network_id, net) | 902 | network_ref = db.network_update(context, network_ref['id'], net) |
961 | 885 | else: | 903 | else: |
967 | 886 | address = network['vpn_public_address'] | 904 | address = network_ref['vpn_public_address'] |
968 | 887 | self.driver.ensure_vlan_bridge(network['vlan'], | 905 | self.driver.ensure_vlan_bridge(network_ref['vlan'], |
969 | 888 | network['bridge'], | 906 | network_ref['bridge'], |
970 | 889 | network['bridge_interface'], | 907 | network_ref['bridge_interface'], |
971 | 890 | network) | 908 | network_ref) |
972 | 891 | 909 | ||
973 | 892 | # NOTE(vish): only ensure this forward if the address hasn't been set | 910 | # NOTE(vish): only ensure this forward if the address hasn't been set |
974 | 893 | # manually. | 911 | # manually. |
975 | 894 | if address == FLAGS.vpn_ip and hasattr(self.driver, | 912 | if address == FLAGS.vpn_ip and hasattr(self.driver, |
976 | 895 | "ensure_vlan_forward"): | 913 | "ensure_vlan_forward"): |
977 | 896 | self.driver.ensure_vlan_forward(FLAGS.vpn_ip, | 914 | self.driver.ensure_vlan_forward(FLAGS.vpn_ip, |
980 | 897 | network['vpn_public_port'], | 915 | network_ref['vpn_public_port'], |
981 | 898 | network['vpn_private_address']) | 916 | network_ref['vpn_private_address']) |
982 | 899 | if not FLAGS.fake_network: | 917 | if not FLAGS.fake_network: |
984 | 900 | self.driver.update_dhcp(context, network_id) | 918 | self.driver.update_dhcp(context, network_ref) |
985 | 901 | if(FLAGS.use_ipv6): | 919 | if(FLAGS.use_ipv6): |
987 | 902 | self.driver.update_ra(context, network_id) | 920 | self.driver.update_ra(context, network_ref) |
988 | 921 | gateway = utils.get_my_linklocal(network_ref['bridge']) | ||
989 | 922 | self.db.network_update(context, network_ref['id'], | ||
990 | 923 | {'gateway_v6': gateway}) | ||
991 | 903 | 924 | ||
992 | 904 | @property | 925 | @property |
993 | 905 | def _bottom_reserved_ips(self): | 926 | def _bottom_reserved_ips(self): |
994 | 906 | 927 | ||
995 | === modified file 'nova/tests/__init__.py' | |||
996 | --- nova/tests/__init__.py 2011-06-29 17:58:10 +0000 | |||
997 | +++ nova/tests/__init__.py 2011-07-20 18:28:31 +0000 | |||
998 | @@ -59,6 +59,7 @@ | |||
999 | 59 | network.create_networks(ctxt, | 59 | network.create_networks(ctxt, |
1000 | 60 | label='test', | 60 | label='test', |
1001 | 61 | cidr=FLAGS.fixed_range, | 61 | cidr=FLAGS.fixed_range, |
1002 | 62 | multi_host=FLAGS.multi_host, | ||
1003 | 62 | num_networks=FLAGS.num_networks, | 63 | num_networks=FLAGS.num_networks, |
1004 | 63 | network_size=FLAGS.network_size, | 64 | network_size=FLAGS.network_size, |
1005 | 64 | cidr_v6=FLAGS.fixed_range_v6, | 65 | cidr_v6=FLAGS.fixed_range_v6, |
1006 | @@ -68,7 +69,7 @@ | |||
1007 | 68 | vpn_start=FLAGS.vpn_start, | 69 | vpn_start=FLAGS.vpn_start, |
1008 | 69 | vlan_start=FLAGS.vlan_start) | 70 | vlan_start=FLAGS.vlan_start) |
1009 | 70 | for net in db.network_get_all(ctxt): | 71 | for net in db.network_get_all(ctxt): |
1011 | 71 | network.set_network_host(ctxt, net['id']) | 72 | network.set_network_host(ctxt, net) |
1012 | 72 | 73 | ||
1013 | 73 | cleandb = os.path.join(FLAGS.state_path, FLAGS.sqlite_clean_db) | 74 | cleandb = os.path.join(FLAGS.state_path, FLAGS.sqlite_clean_db) |
1014 | 74 | shutil.copyfile(testdb, cleandb) | 75 | shutil.copyfile(testdb, cleandb) |
1015 | 75 | 76 | ||
1016 | === modified file 'nova/tests/test_libvirt.py' | |||
1017 | --- nova/tests/test_libvirt.py 2011-06-28 16:20:02 +0000 | |||
1018 | +++ nova/tests/test_libvirt.py 2011-07-20 18:28:31 +0000 | |||
1019 | @@ -58,6 +58,7 @@ | |||
1020 | 58 | 'cidr': fake_ip, | 58 | 'cidr': fake_ip, |
1021 | 59 | 'cidr_v6': fake_ip} | 59 | 'cidr_v6': fake_ip} |
1022 | 60 | mapping = {'mac': fake, | 60 | mapping = {'mac': fake, |
1023 | 61 | 'dhcp_server': fake, | ||
1024 | 61 | 'gateway': fake, | 62 | 'gateway': fake, |
1025 | 62 | 'gateway6': fake, | 63 | 'gateway6': fake, |
1026 | 63 | 'ips': [{'ip': fake_ip}, {'ip': fake_ip}]} | 64 | 'ips': [{'ip': fake_ip}, {'ip': fake_ip}]} |
1027 | 64 | 65 | ||
1028 | === modified file 'nova/tests/test_network.py' | |||
1029 | --- nova/tests/test_network.py 2011-07-11 14:49:34 +0000 | |||
1030 | +++ nova/tests/test_network.py 2011-07-20 18:28:31 +0000 | |||
1031 | @@ -45,6 +45,7 @@ | |||
1032 | 45 | networks = [{'id': 0, | 45 | networks = [{'id': 0, |
1033 | 46 | 'label': 'test0', | 46 | 'label': 'test0', |
1034 | 47 | 'injected': False, | 47 | 'injected': False, |
1035 | 48 | 'multi_host': False, | ||
1036 | 48 | 'cidr': '192.168.0.0/24', | 49 | 'cidr': '192.168.0.0/24', |
1037 | 49 | 'cidr_v6': '2001:db8::/64', | 50 | 'cidr_v6': '2001:db8::/64', |
1038 | 50 | 'gateway_v6': '2001:db8::1', | 51 | 'gateway_v6': '2001:db8::1', |
1039 | @@ -62,6 +63,7 @@ | |||
1040 | 62 | {'id': 1, | 63 | {'id': 1, |
1041 | 63 | 'label': 'test1', | 64 | 'label': 'test1', |
1042 | 64 | 'injected': False, | 65 | 'injected': False, |
1043 | 66 | 'multi_host': False, | ||
1044 | 65 | 'cidr': '192.168.1.0/24', | 67 | 'cidr': '192.168.1.0/24', |
1045 | 66 | 'cidr_v6': '2001:db9::/64', | 68 | 'cidr_v6': '2001:db9::/64', |
1046 | 67 | 'gateway_v6': '2001:db9::1', | 69 | 'gateway_v6': '2001:db9::1', |
1047 | @@ -122,20 +124,6 @@ | |||
1048 | 122 | self.network = network_manager.FlatManager(host=HOST) | 124 | self.network = network_manager.FlatManager(host=HOST) |
1049 | 123 | self.network.db = db | 125 | self.network.db = db |
1050 | 124 | 126 | ||
1051 | 125 | def test_set_network_hosts(self): | ||
1052 | 126 | self.mox.StubOutWithMock(db, 'network_get_all') | ||
1053 | 127 | self.mox.StubOutWithMock(db, 'network_set_host') | ||
1054 | 128 | self.mox.StubOutWithMock(db, 'network_update') | ||
1055 | 129 | |||
1056 | 130 | db.network_get_all(mox.IgnoreArg()).AndReturn([networks[0]]) | ||
1057 | 131 | db.network_set_host(mox.IgnoreArg(), | ||
1058 | 132 | networks[0]['id'], | ||
1059 | 133 | mox.IgnoreArg()).AndReturn(HOST) | ||
1060 | 134 | db.network_update(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) | ||
1061 | 135 | self.mox.ReplayAll() | ||
1062 | 136 | |||
1063 | 137 | self.network.set_network_hosts(None) | ||
1064 | 138 | |||
1065 | 139 | def test_get_instance_nw_info(self): | 127 | def test_get_instance_nw_info(self): |
1066 | 140 | self.mox.StubOutWithMock(db, 'fixed_ip_get_by_instance') | 128 | self.mox.StubOutWithMock(db, 'fixed_ip_get_by_instance') |
1067 | 141 | self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance') | 129 | self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance') |
1068 | @@ -149,7 +137,7 @@ | |||
1069 | 149 | mox.IgnoreArg()).AndReturn(flavor) | 137 | mox.IgnoreArg()).AndReturn(flavor) |
1070 | 150 | self.mox.ReplayAll() | 138 | self.mox.ReplayAll() |
1071 | 151 | 139 | ||
1073 | 152 | nw_info = self.network.get_instance_nw_info(None, 0, 0) | 140 | nw_info = self.network.get_instance_nw_info(None, 0, 0, None) |
1074 | 153 | 141 | ||
1075 | 154 | self.assertTrue(nw_info) | 142 | self.assertTrue(nw_info) |
1076 | 155 | 143 | ||
1077 | @@ -164,6 +152,7 @@ | |||
1078 | 164 | self.assertDictMatch(nw[0], check) | 152 | self.assertDictMatch(nw[0], check) |
1079 | 165 | 153 | ||
1080 | 166 | check = {'broadcast': '192.168.%s.255' % i, | 154 | check = {'broadcast': '192.168.%s.255' % i, |
1081 | 155 | 'dhcp_server': '192.168.%s.1' % i, | ||
1082 | 167 | 'dns': 'DONTCARE', | 156 | 'dns': 'DONTCARE', |
1083 | 168 | 'gateway': '192.168.%s.1' % i, | 157 | 'gateway': '192.168.%s.1' % i, |
1084 | 169 | 'gateway6': '2001:db%s::1' % i8, | 158 | 'gateway6': '2001:db%s::1' % i8, |
1085 | 170 | 159 | ||
1086 | === modified file 'nova/virt/libvirt/connection.py' | |||
1087 | --- nova/virt/libvirt/connection.py 2011-07-20 16:17:44 +0000 | |||
1088 | +++ nova/virt/libvirt/connection.py 2011-07-20 18:28:31 +0000 | |||
1089 | @@ -928,7 +928,6 @@ | |||
1090 | 928 | 928 | ||
1091 | 929 | def _get_nic_for_xml(self, network, mapping): | 929 | def _get_nic_for_xml(self, network, mapping): |
1092 | 930 | # Assume that the gateway also acts as the dhcp server. | 930 | # Assume that the gateway also acts as the dhcp server. |
1093 | 931 | dhcp_server = mapping['gateway'] | ||
1094 | 932 | gateway6 = mapping.get('gateway6') | 931 | gateway6 = mapping.get('gateway6') |
1095 | 933 | mac_id = mapping['mac'].replace(':', '') | 932 | mac_id = mapping['mac'].replace(':', '') |
1096 | 934 | 933 | ||
1097 | @@ -951,7 +950,7 @@ | |||
1098 | 951 | 'bridge_name': network['bridge'], | 950 | 'bridge_name': network['bridge'], |
1099 | 952 | 'mac_address': mapping['mac'], | 951 | 'mac_address': mapping['mac'], |
1100 | 953 | 'ip_address': mapping['ips'][0]['ip'], | 952 | 'ip_address': mapping['ips'][0]['ip'], |
1102 | 954 | 'dhcp_server': dhcp_server, | 953 | 'dhcp_server': mapping['dhcp_server'], |
1103 | 955 | 'extra_params': extra_params, | 954 | 'extra_params': extra_params, |
1104 | 956 | } | 955 | } |
1105 | 957 | 956 |
48: multi_host = multi_host == 'T'
I think something like:
multi_host = multi_host. lower() [:1] == 't'
so it can accept any "truthy" value would be more user friendly.