def reassign_volume(request, volume_id, args): req = utils.get_json_body(request) log.debug("User: %s, Volume: %s Action: reassign_volume, Request: %s", request.user_uniq, volume_id, args) shared_to_project = args.get("shared_to_project", False) if shared_to_project and not settings.CYCLADES_SHARED_RESOURCES_ENABLED: raise faults.Forbidden("Sharing resource to the members of the project" " is not permitted") project = args.get("project") if project is None: raise faults.BadRequest("Missing 'project' attribute.") volume = util.get_volume(request.user_uniq, request.user_projects, volume_id, for_update=True, non_deleted=True) if request.user_uniq != volume.userid: raise faults.Forbidden("Action 'reassign' is allowed only to the owner" " of the volume.") volumes.reassign_volume(volume, project, shared_to_project) log.info("User %s reassigned volume %s to project %s, shared: %s", request.user_uniq, volume.id, project, shared_to_project) return HttpResponse(status=200)
def delete(network_id, credentials, atomic_context=None): network = util.get_network(network_id, credentials, for_update=True, non_deleted=True) if network.public and not credentials.is_admin: raise faults.Forbidden("Cannot delete the public network.") validate_network_action(network, "DESTROY") if network.nics.exists(): raise faults.Conflict("Cannot delete network. There are ports still" " configured on network network %s" % network.id) if network.ips.filter(deleted=False, floating_ip=True).exists(): msg = "Cannot delete netowrk. Network has allocated floating IPs." raise faults.Conflict(msg) network.action = "DESTROY" # Mark network as drained to prevent automatic allocation of # public/floating IPs while the network is being deleted if network.public: network.drained = True network.save() # Delete network to all backends that exists for bnet in network.backend_networks.exclude(operstate="DELETED"): backend_mod.delete_network(network, bnet.backend) else: # If network does not exist in any backend, update the network state backend_mod.update_network_state(network, atomic_context=atomic_context) return network
def reassign_volume(volume_id, project, shared_to_project, credentials, atomic_context=None): volume = util.get_volume(credentials, volume_id, for_update=True, non_deleted=True) if not credentials.is_admin and credentials.userid != volume.userid: raise faults.Forbidden("Action 'reassign' is allowed only to the owner" " of the volume.") if volume.index == 0: raise faults.Conflict("Cannot reassign: %s is a system volume" % volume.id) server = volume.machine if server is not None: commands.validate_server_action(server, "REASSIGN") if volume.project == project: if volume.shared_to_project != shared_to_project: log.info("%s volume %s to project %s", "Sharing" if shared_to_project else "Unsharing", volume, project) volume.shared_to_project = shared_to_project volume.save() else: action_fields = {"to_project": project, "from_project": volume.project} log.info("Reassigning volume %s from project %s to %s, shared: %s", volume, volume.project, project, shared_to_project) volume.project = project volume.shared_to_project = shared_to_project volume.save() quotas.issue_and_accept_commission(volume, action="REASSIGN", action_fields=action_fields, atomic_context=atomic_context) return volume
def get_vm(server_id, user_id, projects, for_update=False, non_deleted=False, non_suspended=False, prefetch_related=None): """Find a VirtualMachine instance based on ID and owner.""" try: server_id = int(server_id) servers = VirtualMachine.objects.for_user(userid=user_id, projects=projects) if for_update: servers = servers.select_for_update() if prefetch_related is not None: if isinstance(prefetch_related, list): servers = servers.prefetch_related(*prefetch_related) else: servers = servers.prefetch_related(prefetch_related) vm = servers.get(id=server_id) if non_deleted and vm.deleted: raise faults.BadRequest("Server has been deleted.") if non_suspended and vm.suspended: raise faults.Forbidden("Administratively Suspended VM") return vm except (ValueError, TypeError): raise faults.BadRequest('Invalid server ID.') except VirtualMachine.DoesNotExist: raise faults.ItemNotFound('Server not found.')
def _port_for_request(user_id, network_dict): if not isinstance(network_dict, dict): raise faults.BadRequest("Malformed request. Invalid 'networks' field") port_id = network_dict.get("port") network_id = network_dict.get("uuid") if port_id is not None: return util.get_port(port_id, user_id, for_update=True) elif network_id is not None: address = network_dict.get("fixed_ip") network = util.get_network(network_id, user_id, non_deleted=True) if network.public: if network.subnet4 is not None: if not "fixed_ip" in network_dict: return create_public_ipv4_port(user_id, network) elif address is None: msg = "Cannot connect to public network" raise faults.BadRequest(msg % network.id) else: return create_public_ipv4_port(user_id, network, address) else: raise faults.Forbidden("Cannot connect to IPv6 only public" " network %" % network.id) else: return _create_port(user_id, network, address=address) else: raise faults.BadRequest("Network 'uuid' or 'port' attribute" " is required.")
def copy_or_move_object(request, src_account, src_container, src_name, dest_account, dest_container, dest_name, move=False, delimiter=None, listing_limit=None): """Copy or move an object.""" if 'ignore_content_type' in request.GET and 'CONTENT_TYPE' in request.META: del(request.META['CONTENT_TYPE']) content_type, meta, permissions, public = get_object_headers(request) src_version = request.META.get('HTTP_X_SOURCE_VERSION') try: if move: version_id = request.backend.move_object( request.user_uniq, src_account, src_container, src_name, dest_account, dest_container, dest_name, content_type, 'pithos', meta, False, permissions, delimiter, listing_limit=listing_limit) else: version_id = request.backend.copy_object( request.user_uniq, src_account, src_container, src_name, dest_account, dest_container, dest_name, content_type, 'pithos', meta, False, permissions, src_version, delimiter, listing_limit=listing_limit) except NotAllowedError: raise faults.Forbidden('Not allowed') except (ItemNotExists, VersionNotExists): raise faults.ItemNotFound('Container or object does not exist') except ValueError: raise faults.BadRequest('Invalid sharing header') except QuotaError, e: raise faults.RequestEntityTooLarge('Quota error: %s' % e)
def delete_network(request, network_id): # Normal Response Code: 204 # Error Response Codes: computeFault (400, 500), # serviceUnavailable (503), # unauthorized (401), # forbidden (403) # itemNotFound (404), # overLimit (413) log.info('delete_network %s', network_id) net = util.get_network(network_id, request.user_uniq, for_update=True) if net.public: raise faults.Forbidden('Can not delete the public network.') if net.deleted: raise faults.BadRequest("Network has been deleted.") if net.machines.all(): # Nics attached on network raise faults.NetworkInUse('Machines are connected to network.') net.action = 'DESTROY' net.save() backend_networks = net.backend_networks.exclude(operstate="DELETED") for bnet in backend_networks: backend.delete_network(net, bnet.backend) if not backend_networks: backend.update_network_state(net) return HttpResponse(status=204)
def update_network_name(request, network_id): # Normal Response Code: 204 # Error Response Codes: computeFault (400, 500), # serviceUnavailable (503), # unauthorized (401), # badRequest (400), # forbidden (403) # badMediaType(415), # itemNotFound (404), # overLimit (413) req = utils.get_request_dict(request) log.info('update_network_name %s', network_id) try: name = req['network']['name'] except (TypeError, KeyError): raise faults.BadRequest('Malformed request.') net = util.get_network(network_id, request.user_uniq) if net.public: raise faults.Forbidden('Can not rename the public network.') if net.deleted: raise faults.BadRequest("Network has been deleted.") net.name = name net.save() return HttpResponse(status=204)
def get_flavor(flavor_id, credentials, include_deleted=False, for_project=None, include_for_user=False): """Return a Flavor instance or raise ItemNotFound.""" try: flavor_id = int(flavor_id) flavors = policy.FlavorPolicy\ .filter_list(credentials, include_for_user=include_for_user)\ .select_related("volume_type") if not include_deleted: flavors = flavors.filter(deleted=False) flavor = flavors.get(id=flavor_id) if not policy.FlavorPolicy\ .has_access_to_flavor(flavor, credentials, project=for_project, include_for_user=include_for_user): raise faults.Forbidden("Insufficient access") return flavor except (ValueError, TypeError): raise faults.BadRequest("Invalid flavor ID '%s'" % flavor_id) except Flavor.DoesNotExist: raise faults.ItemNotFound('Flavor not found.')
def rename(network_id, name, credentials): network = util.get_network(network_id, credentials, for_update=True, non_deleted=True) if network.public: raise faults.Forbidden("Cannot rename the public network.") return _rename(network, name)
def delete_port(request, port_id): log.info('delete_port %s', port_id) user_id = request.user_uniq port = util.get_port(port_id, user_id, for_update=True) # Deleting port that is connected to a public network is allowed only if # the port has an associated floating IP address. if port.network.public and not port.ips.filter(floating_ip=True, deleted=False).exists(): raise faults.Forbidden("Cannot disconnect from public network.") vm = port.machine if vm is not None and vm.suspended: raise faults.Forbidden("Administratively Suspended VM.") servers.delete_port(port) return HttpResponse(status=204)
def delete_port(port_id, credentials): user_id = credentials.userid port = util.get_port(port_id, credentials, for_update=True) # Deleting port that is connected to a public network is allowed only if # the port has an associated floating IP address. if port.network.public and not port.ips.filter(floating_ip=True, deleted=False).exists(): raise faults.Forbidden("Cannot disconnect from public network.") vm = port.machine if vm is not None and vm.suspended: raise faults.Forbidden("Administratively Suspended VM.") _delete_port(port) log.info("User %s deleted port %s", user_id, port_id)
def unsuspend(server_id, credentials=None, atomic_context=None): if not credentials.is_admin: raise faults.Forbidden("Cannot unsuspend vm.") with commands.ServerCommand("UNSUSPEND", server_id, credentials, atomic_context) as vm: vm.suspended = False vm.save() log.info("Unsuspended %s", vm) return vm
def reassign(server_id, project, shared_to_project, credentials=None, atomic_context=None): vm = util.get_vm(server_id, credentials, for_update=True, non_deleted=True, non_suspended=True) commands.validate_server_action(vm, "REASSIGN") if vm.project == project: if vm.shared_to_project != shared_to_project: log.info("%s VM %s to project %s", "Sharing" if shared_to_project else "Unsharing", vm, project) vm.shared_to_project = shared_to_project vm.volumes.filter(index=0, deleted=False)\ .update(shared_to_project=shared_to_project) vm.save() else: action_fields = {"to_project": project, "from_project": vm.project} log.info("Reassigning VM %s from project %s to %s, shared: %s", vm, vm.project, project, shared_to_project) if not (vm.backend.public or vm.backend.projects.filter(project=project).exists()): raise faults.Forbidden("Cannot reassign VM. Target project " "doesn't have access to the VM's backend.") if not FlavorPolicy.has_access_to_flavor( vm.flavor, credentials, project=project): raise faults.Forbidden("Cannot reassign VM. Target project " "doesn't have access to the VM's flavor.") vm.project = project vm.shared_to_project = shared_to_project vm.save() vm.volumes.filter(index=0, deleted=False)\ .update(project=project, shared_to_project=shared_to_project) quotas.issue_and_accept_commission(vm, action="REASSIGN", action_fields=action_fields, atomic_context=atomic_context) return vm
def create_new_keypair(request): """Generates or imports a keypair. Normal response code: 201 Error response codes: badRequest(400), unauthorized(401), forbidden(403), conflict(409) """ userid = request.credentials.userid if PublicKeyPair.user_limit_exceeded(userid): return HttpResponseServerError("SSH keys limit exceeded") req = utils.get_json_body(request) try: keypair = req['keypair'] assert (isinstance(req, dict)) name = keypair['name'] except (KeyError, AssertionError): raise faults.BadRequest('Malformed request.') if re.match(key_name_regex, name) is None: raise faults.BadRequest('Invalid name format') try: # If the key with the same name exists in the database # a conflict error will be raised util.get_keypair(name, userid) # If we get past this point then the key is already present # in the database raise faults.Conflict('A keypair with that name already exists') except faults.ItemNotFound: new_keypair = PublicKeyPair(name=name, user=userid) gen_keypair = None try: new_keypair.content = keypair['public_key'] except KeyError: # If the public_key field is omitted, generate a new # keypair and return both the private and the public key if not SUPPORT_GENERATE_KEYS: raise faults.Forbidden( "Application does not support ssh keys generation") gen_keypair = generate_keypair() new_keypair.content = gen_keypair['public'] new_keypair.save() data = keypair_to_dict(new_keypair) if gen_keypair is not None: data['keypair']['private_key'] = gen_keypair['private'] return HttpResponse(json.dumps(data), status=201)
def reassign(request, floating_ip, args): if request.user_uniq != floating_ip.userid: raise faults.Forbidden("Action 'reassign' is allowed only to the owner" " of the floating IP.") shared_to_project = args.get("shared_to_project", False) if shared_to_project and not settings.CYCLADES_SHARED_RESOURCES_ENABLED: raise faults.Forbidden("Sharing resource to the members of the project" " is not permitted") project = args.get("project") if project is None: raise faults.BadRequest("Missing 'project' attribute.") ips.reassign_floating_ip(floating_ip, project, shared_to_project) log.info("User %s reaasigned floating IP %s to project %s, shared: %s", request.user_uniq, floating_ip.id, project, shared_to_project) return HttpResponse(status=200)
def undrain(network_id, credentials): if not credentials.is_admin: raise faults.Forbidden("Cannot unset network's drained flag.") network = util.get_network(network_id, credentials, for_update=True, non_deleted=True) validate_network_action(network, "UNDRAIN") log.info("Undraining %s", network) network.drained = False network.save()
def create_server(request): # Normal Response Code: 202 # Error Response Codes: computeFault (400, 500), # serviceUnavailable (503), # unauthorized (401), # badMediaType(415), # itemNotFound (404), # badRequest (400), # serverCapacityUnavailable (503), # overLimit (413) req = utils.get_request_dict(request) user_id = request.user_uniq log.info('create_server user: %s request: %s', user_id, req) try: server = req['server'] name = server['name'] metadata = server.get('metadata', {}) assert isinstance(metadata, dict) image_id = server['imageRef'] flavor_id = server['flavorRef'] personality = server.get('personality', []) assert isinstance(personality, list) networks = server.get("networks") if networks is not None: assert isinstance(networks, list) except (KeyError, AssertionError): raise faults.BadRequest("Malformed request") # Verify that personalities are well-formed util.verify_personality(personality) # Get image information image = util.get_image_dict(image_id, user_id) # Get flavor (ensure it is active) flavor = util.get_flavor(flavor_id, include_deleted=False) if not flavor.allow_create: msg = ("It is not allowed to create a server from flavor with id '%d'," " see 'allow_create' flavor attribute") raise faults.Forbidden(msg % flavor.id) # Generate password password = util.random_password() vm = servers.create(user_id, name, password, flavor, image, metadata=metadata, personality=personality, networks=networks) server = vm_to_dict(vm, detail=True) server['status'] = 'BUILD' server['adminPass'] = password response = render_server(request, server, status=202) return response
def reassign(network_id, project, shared_to_project, credentials, atomic_context=None): network = util.get_network(network_id, credentials, for_update=True, non_deleted=True) if network.public: raise faults.Forbidden("Cannot reassign public network") if not credentials.is_admin and credentials.userid != network.userid: raise faults.Forbidden("Action 'reassign' is allowed only to the owner" " of the network.") validate_network_action(network, "REASSIGN") if network.project == project: if network.shared_to_project != shared_to_project: log.info("%s network %s to project %s", "Sharing" if shared_to_project else "Unsharing", network, project) network.shared_to_project = shared_to_project network.save() else: action_fields = { "to_project": project, "from_project": network.project } log.info("Reassigning network %s from project %s to %s, shared: %s", network, network.project, project, shared_to_project) network.project = project network.shared_to_project = shared_to_project network.save() quotas.issue_and_accept_commission(network, action="REASSIGN", action_fields=action_fields, atomic_context=atomic_context) return network
def put_object_block(request, hashmap, data, offset, is_snapshot): """Put one block of data at the given offset.""" bi = int(offset / request.backend.block_size) bo = offset % request.backend.block_size bl = min(len(data), request.backend.block_size - bo) if bi < len(hashmap): try: hashmap[bi] = request.backend.update_block(hashmap[bi], data[:bl], offset=bo, is_snapshot=is_snapshot) except IllegalOperationError, e: raise faults.Forbidden(e[0])
def reassign(request, floating_ip_id, args): credentials = request.credentials shared_to_project = args.get("shared_to_project", False) if shared_to_project and not settings.CYCLADES_SHARED_RESOURCES_ENABLED: raise faults.Forbidden("Sharing resource to the members of the project" " is not permitted") project = args.get("project") if project is None: raise faults.BadRequest("Missing 'project' attribute.") ips.reassign_floating_ip(floating_ip_id, project, shared_to_project, credentials) log.info("User %s reaasigned floating IP %s to project %s, shared: %s", credentials.userid, floating_ip_id, project, shared_to_project) return HttpResponse(status=200)
def wrapper(request, *args, **kwargs): # The args variable may contain up to (account, container, object). if len(args) > 1 and len(args[1]) > 256: raise faults.BadRequest("Container name too large") if len(args) > 2 and len(args[2]) > 1024: raise faults.BadRequest('Object name too large.') success_status = False try: # Add a PithosBackend as attribute of the request object request.backend = get_backend() request.backend.pre_exec(lock_container_path) # Many API method expect thet X-Auth-Token in request,token request.token = request.x_auth_token update_request_headers(request) response = func(request, *args, **kwargs) update_response_headers(request, response) success_status = True return response except LimitExceeded as le: raise faults.BadRequest(le.args[0]) except BrokenSnapshot as bs: raise faults.BadRequest(bs.args[0]) except (IllegalOperationError, NotAllowedError) as e: raise faults.Forbidden(smart_str_(e)) except (InconsistentContentSize, InvalidPolicy, LimitExceeded, InvalidHash, ValueError) as e: raise faults.BadRequest(smart_str_(e)) except (ItemNotExists, VersionNotExists) as e: raise faults.ItemNotFound(smart_str_(e)) except ContainerNotEmpty as e: raise faults.Conflict(smart_str_(e)) except QuotaError as e: raise faults.RequestEntityTooLarge('Quota error: %s' % e) finally: # Always close PithosBackend connection if getattr(request, "backend", None) is not None: request.backend.post_exec(success_status) request.backend.close()
def network_action(request, network_id): req = utils.get_request_dict(request) log.debug('network_action %s %s', network_id, req) if len(req) != 1: raise faults.BadRequest('Malformed request.') net = util.get_network(network_id, request.user_uniq) if net.public: raise faults.Forbidden('Can not modify the public network.') if net.deleted: raise faults.BadRequest("Network has been deleted.") try: key = req.keys()[0] val = req[key] assert isinstance(val, dict) return network_actions[key](request, net, req[key]) except KeyError: raise faults.BadRequest('Unknown action.') except AssertionError: raise faults.BadRequest('Invalid argument.')
def reassign_volume(request, volume_id, args): credentials = request.credentials req = utils.get_json_body(request) log.debug("User: %s, Volume: %s Action: reassign_volume, Request: %s", credentials.userid, volume_id, args) shared_to_project = args.get("shared_to_project", False) if shared_to_project and not settings.CYCLADES_SHARED_RESOURCES_ENABLED: raise faults.Forbidden("Sharing resource to the members of the project" " is not permitted") project = args.get("project") if project is None: raise faults.BadRequest("Missing 'project' attribute.") volumes.reassign_volume(volume_id, project, shared_to_project, credentials) log.info("User %s reassigned volume %s to project %s, shared: %s", credentials.userid, volume_id, project, shared_to_project) return HttpResponse(status=200)
def get_vm(server_id, user_id, for_update=False, non_deleted=False, non_suspended=False): """Find a VirtualMachine instance based on ID and owner.""" try: server_id = int(server_id) servers = VirtualMachine.objects if for_update: servers = servers.select_for_update() vm = servers.get(id=server_id, userid=user_id) if non_deleted and vm.deleted: raise faults.BadRequest("Server has been deleted.") if non_suspended and vm.suspended: raise faults.Forbidden("Administratively Suspended VM") return vm except ValueError: raise faults.BadRequest('Invalid server ID.') except VirtualMachine.DoesNotExist: raise faults.ItemNotFound('Server not found.')
def reassign_floating_ip(floating_ip_id, project, shared_to_project, credentials, atomic_context=None): floating_ip = util.get_floating_ip_by_id(credentials, floating_ip_id, for_update=True) if not credentials.is_admin and credentials.userid != floating_ip.userid: raise faults.Forbidden("Action 'reassign' is allowed only to the owner" " of the floating IP.") validate_ip_action(floating_ip, "REASSIGN", silent=False) if floating_ip.project == project: if floating_ip.shared_to_project != shared_to_project: log.info("%s floating_ip %s to project %s", "Sharing" if shared_to_project else "Unsharing", floating_ip, project) floating_ip.shared_to_project = shared_to_project floating_ip.save() else: action_fields = { "to_project": project, "from_project": floating_ip.project } log.info( "Reassigning floating_ip %s from project %s to %s, shared: %s", floating_ip, floating_ip.project, project, shared_to_project) floating_ip.project = project floating_ip.shared_to_project = shared_to_project floating_ip.save() quotas.issue_and_accept_commission(floating_ip, action="REASSIGN", action_fields=action_fields, atomic_context=atomic_context) return floating_ip
src_version, delimiter, listing_limit=listing_limit) except NotAllowedError: raise faults.Forbidden('Not allowed') except (ItemNotExists, VersionNotExists): raise faults.ItemNotFound('Container or object does not exist') except ValueError: raise faults.BadRequest('Invalid sharing header') except QuotaError, e: raise faults.RequestEntityTooLarge('Quota error: %s' % e) if public is not None: try: request.backend.update_object_public( request.user_uniq, dest_account, dest_container, dest_name, public) except NotAllowedError: raise faults.Forbidden('Not allowed') except ItemNotExists: raise faults.ItemNotFound('Object does not exist') return version_id def get_int_parameter(p): if p is not None: try: p = int(p) except ValueError: return None if p < 0: return None return p
def suspend(request, server_id, args): raise faults.Forbidden('User is not allowed to suspend his server')
def create_server(request): # Normal Response Code: 202 # Error Response Codes: computeFault (400, 500), # serviceUnavailable (503), # unauthorized (401), # badMediaType(415), # itemNotFound (404), # badRequest (400), # serverCapacityUnavailable (503), # overLimit (413) req = utils.get_json_body(request) credentials = request.credentials user_id = credentials.userid log.info("User: %s, Action: create_server, Request: %s", user_id, req) try: server = req['server'] name = server['name'] metadata = server.get('metadata', {}) assert isinstance(metadata, dict) image_id = server['imageRef'] flavor_id = server['flavorRef'] personality = server.get('personality', []) assert isinstance(personality, list) networks = server.get("networks") if networks is not None: assert isinstance(networks, list) project = server.get("project") shared_to_project = server.get("shared_to_project", False) key_name = server.get('key_name') user_data = server.get('user_data', "") SNF_key_names = server.get('SNF:key_names', []) assert isinstance(SNF_key_names, list) except (KeyError, AssertionError): raise faults.BadRequest("Malformed request") volumes = None dev_map = server.get("block_device_mapping_v2") if dev_map is not None: allowed_types = VOLUME_SOURCE_TYPES[:] if snapshots_enabled_for_user(request.user): allowed_types.append('snapshot') volumes = parse_block_device_mapping(dev_map, allowed_types) # If no project is provided, use the user's system project as default. if project is None: project = user_id # Verify that personalities are well-formed util.verify_personality(personality) # Verify that user_data are well-formed util.verify_user_data(user_data) # Get flavor (ensure it is active and project has access) flavor = util.get_flavor(flavor_id, credentials, include_deleted=False, for_project=project) if not util.can_create_flavor(flavor, request.user): msg = ("It is not allowed to create a server from flavor with id '%d'," " see 'allow_create' flavor attribute") raise faults.Forbidden(msg % flavor.id) # Generate password password = util.random_password() if key_name is not None: # If both key_name and SNF:key_names are provided we should # raise an error if len(SNF_key_names) > 0: raise faults.BadRequest('Only one of the SNF:key_names and' 'key_name can be set') # If only key_name is provided then we will set key_names as # a list with only one element else: key_names = [key_name] else: # In case key_name is not provided we will set key_names to the # value of SNF:key_names. We don't need to check if it is provided # since even if it is not, its value will be [] # Remove duplicate key names key_names = list(set(SNF_key_names)) vm = servers.create(credentials, name, password, flavor, image_id, metadata=metadata, personality=personality, user_data=user_data, project=project, networks=networks, volumes=volumes, shared_to_project=shared_to_project, key_names=key_names) log.info("User %s created VM %s, shared: %s", user_id, vm.id, shared_to_project) server = vm_to_dict(vm, detail=True) server['status'] = 'BUILD' server['adminPass'] = password set_password_in_cache(server['id'], password) response = render_server(request, server, status=202) return response
def create_network(request): # Normal Response Code: 202 # Error Response Codes: computeFault (400, 500), # serviceUnavailable (503), # unauthorized (401), # badMediaType(415), # badRequest (400), # forbidden (403) # overLimit (413) try: req = utils.get_request_dict(request) log.info('create_network %s', req) user_id = request.user_uniq try: d = req['network'] name = d['name'] except KeyError: raise faults.BadRequest("Malformed request") # Get and validate flavor. Flavors are still exposed as 'type' in the # API. flavor = d.get("type", None) if flavor is None: raise faults.BadRequest("Missing request parameter 'type'") elif flavor not in Network.FLAVORS.keys(): raise faults.BadRequest("Invalid network type '%s'" % flavor) elif flavor not in settings.API_ENABLED_NETWORK_FLAVORS: raise faults.Forbidden("Can not create network of type '%s'" % flavor) public = d.get("public", False) if public: raise faults.Forbidden("Can not create a public network.") dhcp = d.get('dhcp', True) # Get and validate network parameters subnet = d.get('cidr', '192.168.1.0/24') subnet6 = d.get('cidr6', None) gateway = d.get('gateway', None) gateway6 = d.get('gateway6', None) # Check that user provided a valid subnet util.validate_network_params(subnet, gateway, subnet6, gateway6) try: mode, link, mac_prefix, tags = util.values_from_flavor(flavor) validate_mac(mac_prefix + "0:00:00:00") network = Network.objects.create( name=name, userid=user_id, subnet=subnet, subnet6=subnet6, gateway=gateway, gateway6=gateway6, dhcp=dhcp, flavor=flavor, mode=mode, link=link, mac_prefix=mac_prefix, tags=tags, action='CREATE', state='ACTIVE') except EmptyPool: log.error("Failed to allocate resources for network of type: %s", flavor) raise faults.ServiceUnavailable("Failed to allocate network" " resources") # Issue commission to Quotaholder and accept it since at the end of # this transaction the Network object will be created in the DB. # Note: the following call does a commit! quotas.issue_and_accept_commission(network) except: transaction.rollback() raise else: transaction.commit() networkdict = network_to_dict(network, request.user_uniq) response = render_network(request, networkdict, status=202) return response