Revision cb66110b snf-cyclades-app/synnefo/logic/servers.py
b/snf-cyclades-app/synnefo/logic/servers.py | ||
---|---|---|
13 | 13 |
from synnefo.logic import backend |
14 | 14 |
from synnefo.logic.backend_allocator import BackendAllocator |
15 | 15 |
from synnefo.logic.rapi import GanetiApiError |
16 |
from synnefo.db.models import (NetworkInterface, VirtualMachine, |
|
16 |
from synnefo.db.models import (NetworkInterface, VirtualMachine, Network,
|
|
17 | 17 |
VirtualMachineMetadata, FloatingIP) |
18 | 18 |
|
19 | 19 |
from vncauthproxy.client import request_forwarding as request_vnc_forwarding |
... | ... | |
125 | 125 |
|
126 | 126 |
@transaction.commit_manually |
127 | 127 |
def create(userid, name, password, flavor, image, metadata={}, |
128 |
personality=[], network=None, use_backend=None): |
|
128 |
personality=[], network=None, private_networks=None, |
|
129 |
use_backend=None): |
|
129 | 130 |
if use_backend is None: |
130 | 131 |
# Allocate backend to host the server. Commit after allocation to |
131 | 132 |
# release the locks hold by the backend allocator. |
... | ... | |
154 | 155 |
flavor.disk_provider = None |
155 | 156 |
|
156 | 157 |
try: |
157 |
if network is None: |
|
158 |
# Allocate IP from public network |
|
159 |
(network, address) = util.get_public_ip(use_backend) |
|
160 |
nic = {'ip': address, 'network': network.backend_id} |
|
161 |
else: |
|
162 |
address = util.get_network_free_address(network) |
|
163 |
|
|
164 | 158 |
# We must save the VM instance now, so that it gets a valid |
165 | 159 |
# vm.backend_vm_id. |
166 | 160 |
vm = VirtualMachine.objects.create( |
... | ... | |
171 | 165 |
flavor=flavor, |
172 | 166 |
action="CREATE") |
173 | 167 |
|
174 |
# Create VM's public NIC. Do not wait notification form ganeti hooks to |
|
175 |
# create this NIC, because if the hooks never run (e.g. building error) |
|
176 |
# the VM's public IP address will never be released! |
|
177 |
NetworkInterface.objects.create(machine=vm, network=network, index=0, |
|
178 |
ipv4=address, state="BUILDING") |
|
179 |
|
|
180 | 168 |
log.info("Created entry in DB for VM '%s'", vm) |
181 | 169 |
|
182 | 170 |
# dispatch server created signal |
... | ... | |
188 | 176 |
'img_properties': json.dumps(image['metadata']), |
189 | 177 |
}) |
190 | 178 |
|
179 |
nics = create_instance_nics(vm, userid, private_networks) |
|
180 |
|
|
191 | 181 |
# Also we must create the VM metadata in the same transaction. |
192 | 182 |
for key, val in metadata.items(): |
193 | 183 |
VirtualMachineMetadata.objects.create( |
... | ... | |
205 | 195 |
transaction.commit() |
206 | 196 |
|
207 | 197 |
try: |
208 |
jobID = backend.create_instance(vm, [nic], flavor, image)
|
|
198 |
jobID = backend.create_instance(vm, nics, flavor, image)
|
|
209 | 199 |
# At this point the job is enqueued in the Ganeti backend |
210 | 200 |
vm.backendjobid = jobID |
211 | 201 |
vm.task = "BUILD" |
... | ... | |
213 | 203 |
vm.save() |
214 | 204 |
transaction.commit() |
215 | 205 |
log.info("User %s created VM %s, NIC %s, Backend %s, JobID %s", |
216 |
userid, vm, nic, backend, str(jobID)) |
|
206 |
userid, vm, nics, backend, str(jobID))
|
|
217 | 207 |
except GanetiApiError as e: |
218 | 208 |
log.exception("Can not communicate to backend %s: %s.", |
219 | 209 |
backend, e) |
... | ... | |
232 | 222 |
return vm |
233 | 223 |
|
234 | 224 |
|
225 |
def create_instance_nics(vm, userid, private_networks): |
|
226 |
"""Create NICs for VirtualMachine. |
|
227 |
|
|
228 |
Helper function for allocating IP addresses and creating NICs in the DB |
|
229 |
for a VirtualMachine. Created NICs are the combination of the default |
|
230 |
network policy (defined by administration settings) and the private |
|
231 |
networks defined by the user. |
|
232 |
|
|
233 |
""" |
|
234 |
attachments = [] |
|
235 |
for network_id in settings.DEFAULT_INSTANCE_NETWORKS: |
|
236 |
network, address = None, None |
|
237 |
if network_id == "public": |
|
238 |
network, address = util.get_public_ip(backend=vm.backend) |
|
239 |
else: |
|
240 |
try: |
|
241 |
network = Network.objects.get(id=network_id, deleted=False) |
|
242 |
except Network.DoesNotExist: |
|
243 |
msg = "Invalid configuration. Setting"\ |
|
244 |
" 'DEFAULT_INSTANCE_NETWORKS' contains invalid"\ |
|
245 |
" network '%s'" % network_id |
|
246 |
log.error(msg) |
|
247 |
raise Exception(msg) |
|
248 |
if network.dhcp: |
|
249 |
address = util.get_network_free_address(network) |
|
250 |
attachments.append((network, address)) |
|
251 |
for network_id in private_networks: |
|
252 |
network, address = None, None |
|
253 |
network = util.get_network(network_id, userid, non_deleted=True) |
|
254 |
if network.public: |
|
255 |
raise faults.Forbidden("Can not connect to public network") |
|
256 |
if network.dhcp: |
|
257 |
address = util.get_network_free_address(network) |
|
258 |
attachments.append((network, address)) |
|
259 |
|
|
260 |
nics = [] |
|
261 |
for index, (network, address) in enumerate(attachments): |
|
262 |
# Create VM's public NIC. Do not wait notification form ganeti |
|
263 |
# hooks to create this NIC, because if the hooks never run (e.g. |
|
264 |
# building error) the VM's public IP address will never be |
|
265 |
# released! |
|
266 |
nic = NetworkInterface.objects.create(machine=vm, network=network, |
|
267 |
index=index, ipv4=address, |
|
268 |
state="BUILDING") |
|
269 |
nics.append(nic) |
|
270 |
return nics |
|
271 |
|
|
272 |
|
|
235 | 273 |
@server_command("DESTROY") |
236 | 274 |
def destroy(vm): |
237 | 275 |
log.info("Deleting VM %s", vm) |
Also available in: Unified diff