def create_volume(self, size, display_name=None, metadata=None): """Creates a new Volume. :param size: Size of volume in GB. (Required) :param display_name: Optional Volume Name. :param metadata: An optional dictionary of values for metadata. """ volume = Element("volume", xmlns=XMLNS_11, size=size) if display_name: volume.add_attr('display_name', display_name) if metadata: _metadata = Element('metadata') volume.append(_metadata) for key, value in metadata.items(): meta = Element('meta') meta.add_attr('key', key) meta.append(Text(value)) _metadata.append(meta) resp, body = self.post('os-volumes', str(Document(volume)), self.headers) body = xml_to_json(etree.fromstring(body)) return resp, body
def create_volume(self, size, **kwargs): """Creates a new Volume. :param size: Size of volume in GB. (Required) :param display_name: Optional Volume Name. :param metadata: An optional dictionary of values for metadata. :param volume_type: Optional Name of volume_type for the volume :param snapshot_id: When specified the volume is created from this snapshot :param imageRef: When specified the volume is created from this image """ # NOTE(afazekas): it should use a volume namespace volume = Element("volume", xmlns=XMLNS_11, size=size) if 'metadata' in kwargs: _metadata = Element('metadata') volume.append(_metadata) for key, value in kwargs['metadata'].items(): meta = Element('meta') meta.add_attr('key', key) meta.append(Text(value)) _metadata.append(meta) attr_to_add = kwargs.copy() del attr_to_add['metadata'] else: attr_to_add = kwargs for key, value in attr_to_add.items(): volume.add_attr(key, value) resp, body = self.post('volumes', str(Document(volume)), self.headers) body = xml_to_json(etree.fromstring(body)) return resp, body
def update_server(self, server_id, name=None, meta=None, accessIPv4=None, accessIPv6=None, disk_config=None): doc = Document() server = Element("server") doc.append(server) if name is not None: server.add_attr("name", name) if accessIPv4 is not None: server.add_attr("accessIPv4", accessIPv4) if accessIPv6 is not None: server.add_attr("accessIPv6", accessIPv6) if disk_config is not None: server.add_attr('xmlns:OS-DCF', "http://docs.openstack.org/" "compute/ext/disk_config/api/v1.1") server.add_attr("OS-DCF:diskConfig", disk_config) if meta is not None: metadata = Element("metadata") server.append(metadata) for k, v in meta: meta = Element("meta", key=k) meta.append(Text(v)) metadata.append(meta) resp, body = self.put('servers/%s' % str(server_id), str(doc), self.headers) return resp, xml_to_json(etree.fromstring(body))
def create_volume_type(self, name, **kwargs): """ Creates a new Volume_type. name(Required): Name of volume_type. Following optional keyword arguments are accepted: extra_specs: A dictionary of values to be used as extra_specs. """ vol_type = Element("volume_type", xmlns=XMLNS_11) if name: vol_type.add_attr('name', name) extra_specs = kwargs.get('extra_specs') if extra_specs: _extra_specs = Element('extra_specs') vol_type.append(_extra_specs) for key, value in extra_specs.items(): spec = Element('extra_spec') spec.add_attr('key', key) spec.append(Text(value)) _extra_specs.append(spec) resp, body = self.post('types', str(Document(vol_type)), self.headers) body = xml_to_json(etree.fromstring(body)) return resp, body
def _get_element(self, name, value): if value is None: xml_elem = Element(name) xml_elem.add_attr("xsi:nil", "true") return xml_elem else: return Element(name, value)
def update_server(self, server_id, name=None, meta=None, accessIPv4=None, accessIPv6=None, disk_config=None): doc = Document() server = Element("server") doc.append(server) if name is not None: server.add_attr("name", name) if accessIPv4 is not None: server.add_attr("accessIPv4", accessIPv4) if accessIPv6 is not None: server.add_attr("accessIPv6", accessIPv6) if disk_config is not None: server.add_attr('xmlns:OS-DCF', "http://docs.openstack.org/" "compute/ext/disk_config/api/v1.1") server.add_attr("OS-DCF:diskConfig", disk_config) if meta is not None: metadata = Element("metadata") server.append(metadata) for k, v in meta: meta = Element("meta", key=k) meta.append(Text(v)) metadata.append(meta) resp, body = self.put('servers/%s' % str(server_id), str(doc)) return resp, xml_to_json(etree.fromstring(body))
def create_volume(self, size, **kwargs): """Creates a new Volume. :param size: Size of volume in GB. (Required) :param display_name: Optional Volume Name. :param metadata: An optional dictionary of values for metadata. :param volume_type: Optional Name of volume_type for the volume :param snapshot_id: When specified the volume is created from this snapshot """ volume = Element("volume", xmlns=XMLNS_11, size=size) if 'metadata' in kwargs: _metadata = Element('metadata') volume.append(_metadata) for key, value in kwargs['metadata'].items(): meta = Element('meta') meta.add_attr('key', key) meta.append(Text(value)) _metadata.append(meta) attr_to_add = kwargs.copy() del attr_to_add['metadata'] else: attr_to_add = kwargs for key, value in attr_to_add.items(): volume.add_attr(key, value) resp, body = self.post('volumes', str(Document(volume)), self.headers) body = xml_to_json(etree.fromstring(body)) return resp, body
def create_volume(self, size, **kwargs): """Creates a new Volume. :param size: Size of volume in GB. (Required) :param display_name: Optional Volume Name. :param metadata: An optional dictionary of values for metadata. :param volume_type: Optional Name of volume_type for the volume :param snapshot_id: When specified the volume is created from this snapshot :param imageRef: When specified the volume is created from this image """ # NOTE(afazekas): it should use a volume namespace volume = Element("volume", xmlns=XMLNS_11, size=size) if "metadata" in kwargs: _metadata = Element("metadata") volume.append(_metadata) for key, value in kwargs["metadata"].items(): meta = Element("meta") meta.add_attr("key", key) meta.append(Text(value)) _metadata.append(meta) attr_to_add = kwargs.copy() del attr_to_add["metadata"] else: attr_to_add = kwargs for key, value in attr_to_add.items(): volume.add_attr(key, value) resp, body = self.post("volumes", str(Document(volume)), self.headers) body = xml_to_json(etree.fromstring(body)) return resp, body
def update_endpoint(self, endpoint_id, service_id=None, interface=None, url=None, region=None, enabled=None): """Updates an endpoint with given parameters.""" doc = Document() endpoint = Element("endpoint") doc.append(endpoint) if service_id: endpoint.add_attr("service_id", service_id) if interface: endpoint.add_attr("interface", interface) if url: endpoint.add_attr("url", url) if region: endpoint.add_attr("region", region) if enabled is not None: endpoint.add_attr("enabled", enabled) resp, body = self.patch('endpoints/%s' % str(endpoint_id), str(doc), self.headers) body = self._parse_body(etree.fromstring(body)) return resp, body
def set_flavor_extra_spec(self, flavor_id, specs): """Sets extra Specs to the mentioned flavor.""" extra_specs = Element("extra_specs") for key in specs.keys(): extra_specs.add_attr(key, specs[key]) resp, body = self.post("flavors/%s/flavor-extra-specs" % flavor_id, str(Document(extra_specs)), self.headers) body = xml_to_json(etree.fromstring(body)) return resp, body
def create_volume_transfer(self, vol_id, name=None): """Create a volume transfer.""" post_body = Element("transfer", volume_id=vol_id) if name: post_body.add_attr('name', name) resp, body = self.post('os-volume-transfer', str(Document(post_body))) volume = xml_to_json(etree.fromstring(body)) return resp, volume
def disassociate_floating_ip_from_server(self, floating_ip, server_id): """Disassociate the provided floating IP from a specific server.""" url = "servers/%s/action" % str(server_id) doc = Document() server = Element("removeFloatingIp") doc.append(server) server.add_attr("address", floating_ip) resp, body = self.post(url, str(doc), self.headers) return resp, body
def associate_floating_ip_to_server(self, floating_ip, server_id): """Associate the provided floating IP to a specific server.""" url = "servers/%s/action" % str(server_id) doc = Document() server = Element("addFloatingIp") doc.append(server) server.add_attr("address", floating_ip) resp, body = self.post(url, str(doc)) return resp, body
def create_user(self, name, password, tenant_id, email, **kwargs): """Create a user.""" create_user = Element("user", xmlns=XMLNS, name=name, password=password, tenantId=tenant_id, email=email) if "enabled" in kwargs: create_user.add_attr("enabled", str(kwargs["enabled"]).lower()) resp, body = self.post("users", str(Document(create_user)), self.headers) body = self._parse_body(etree.fromstring(body)) return resp, body
def set_flavor_extra_spec(self, flavor_id, specs): """Sets extra Specs to the mentioned flavor.""" extra_specs = Element("extra_specs") for key in specs.keys(): extra_specs.add_attr(key, specs[key]) resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id, str(Document(extra_specs)), self.headers) body = xml_to_json(etree.fromstring(body)) return resp, body
def remove_flavor_access(self, flavor_id, tenant_id): """Remove flavor access from the specified tenant.""" doc = Document() server = Element("removeTenantAccess") doc.append(server) server.add_attr("tenant", tenant_id) resp, body = self.post('flavors/%s/action' % str(flavor_id), str(doc)) body = self._parse_array_access(etree.fromstring(body)) return resp, body
def add_flavor_access(self, flavor_id, tenant_id): """Add flavor access for the specified tenant.""" doc = Document() server = Element("add_tenant_access") doc.append(server) server.add_attr("tenant_id", tenant_id) resp, body = self.post("flavors/%s/action" % str(flavor_id), str(doc), self.headers) body = self._parse_array_access(etree.fromstring(body)) return resp, body
def serialize(self, body): #TODO(enikanorov): implement better json to xml conversion # expecting the dict with single key root = body.keys()[0] post_body = Element(root) post_body.add_attr('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance') for name, attr in body[root].items(): elt = self._get_element(name, attr) post_body.append(elt) return str(Document(post_body))
def serialize_list(self, body, root_name=None, item_name=None): # expecting dict in form # body = {'resources': [res_dict1, res_dict2, ...] post_body = Element(root_name) post_body.add_attr('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance') for item in body[body.keys()[0]]: elt = Element(item_name) for name, attr in item.items(): elt_content = self._get_element(name, attr) elt.append(elt_content) post_body.append(elt) return str(Document(post_body))
def disable_service(self, host_name, binary): """ Disable service on a host host_name: Name of host binary: Service binary """ post_body = Element("service") post_body.add_attr('binary', binary) post_body.add_attr('host', host_name) resp, body = self.put('os-services/disable', str(Document(post_body))) body = xml_to_json(etree.fromstring(body)) return resp, body
def enable_service(self, host_name, binary): """ Enable service on a host host_name: Name of host binary: Service binary """ post_body = Element("service") post_body.add_attr("binary", binary) post_body.add_attr("host", host_name) resp, body = self.put("os-services/enable", str(Document(post_body))) body = xml_to_json(etree.fromstring(body)) return resp, body
def create_server(self, name, image_ref, flavor_ref, **kwargs): """ Creates an instance of a server. name (Required): The name of the server. image_ref (Required): Reference to the image used to build the server. flavor_ref (Required): The flavor used to build the server. Following optional keyword arguments are accepted: adminPass: Sets the initial root password. key_name: Key name of keypair that was created earlier. meta: A dictionary of values to be used as metadata. personality: A list of dictionaries for files to be injected into the server. security_groups: A list of security group dicts. networks: A list of network dicts with UUID and fixed_ip. user_data: User data for instance. availability_zone: Availability zone in which to launch instance. accessIPv4: The IPv4 access address for the server. accessIPv6: The IPv6 access address for the server. min_count: Count of minimum number of instances to launch. max_count: Count of maximum number of instances to launch. disk_config: Determines if user or admin controls disk configuration. """ server = Element("server", xmlns=XMLNS_11, imageRef=image_ref, flavorRef=flavor_ref, name=name) for attr in ["adminPass", "accessIPv4", "accessIPv6", "key_name"]: if attr in kwargs: server.add_attr(attr, kwargs[attr]) if 'meta' in kwargs: metadata = Element("metadata") server.append(metadata) for k, v in kwargs['meta'].items(): meta = Element("meta", key=k) meta.append(Text(v)) metadata.append(meta) if 'personality' in kwargs: personality = Element('personality') server.append(personality) for k in kwargs['personality']: temp = Element('file', path=k['path']) temp.append(Text(k['contents'])) personality.append(temp) resp, body = self.post('servers', str(Document(server)), self.headers) server = self._parse_server(etree.fromstring(body)) return resp, server
def create_snapshot(self, volume_id, **kwargs): """Creates a new snapshot. volume_id(Required): id of the volume. force: Create a snapshot even if the volume attached (Default=False) display_name: Optional snapshot Name. display_description: User friendly snapshot description. """ # NOTE(afazekas): it should use the volume namespace snapshot = Element("snapshot", xmlns=XMLNS_11, volume_id=volume_id) for key, value in kwargs.items(): snapshot.add_attr(key, value) resp, body = self.post('snapshots', str(Document(snapshot))) body = xml_to_json(etree.fromstring(body)) return resp, body
def update_floating_ip(self, floating_ip_id, **kwargs): uri = '%s/floatingips/%s' % (self.uri_prefix, floating_ip_id) floatingip = Element('floatingip') floatingip.add_attr('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance') for element, content in kwargs.iteritems(): if content is None: xml_elem = Element(element) xml_elem.add_attr("xsi:nil", "true") floatingip.append(xml_elem) else: floatingip.append(Element(element, content)) resp, body = self.put(uri, str(Document(floatingip)), self.headers) body = _root_tag_fetcher_and_xml_to_json_parse(body) return resp, body
def update_host(self, hostname, status=None, maintenance_mode=None, **kwargs): """Update a host.""" request_body = Element(status=status, maintenance_mode=maintenance_mode) if kwargs: for k, v in kwargs.iteritem(): request_body.add_attr(k, v) resp, body = self.put("os-hosts/%s" % str(hostname), str(Document(request_body)), self.headers) node = etree.fromstring(body) body = [xml_to_json(x) for x in node.getchildren()] return resp, body
def update_floating_ip(self, floating_ip_id, **kwargs): uri = '%s/floatingips/%s' % (self.uri_prefix, floating_ip_id) floatingip = Element('floatingip') floatingip.add_attr('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance') for element, content in kwargs.iteritems(): if content is None: xml_elem = Element(element) xml_elem.add_attr("xsi:nil", "true") floatingip.append(xml_elem) else: floatingip.append(Element(element, content)) resp, body = self.put(uri, str(Document(floatingip))) body = _root_tag_fetcher_and_xml_to_json_parse(body) return resp, body
def create_user(self, name, password, tenant_id, email, **kwargs): """Create a user.""" create_user = Element("user", xmlns=XMLNS, name=name, password=password, tenantId=tenant_id, email=email) if 'enabled' in kwargs: create_user.add_attr('enabled', str(kwargs['enabled']).lower()) resp, body = self.post('users', str(Document(create_user)), self.headers) body = self._parse_body(etree.fromstring(body)) return resp, body
def create_flavor(self, name, ram, vcpus, disk, flavor_id, **kwargs): """Creates a new flavor or instance type.""" flavor = Element("flavor", xmlns=XMLNS_V3, ram=ram, vcpus=vcpus, disk=disk, id=flavor_id, name=name) if kwargs.get("rxtx"): flavor.add_attr("rxtx_factor", kwargs.get("rxtx")) if kwargs.get("swap"): flavor.add_attr("swap", kwargs.get("swap")) if kwargs.get("ephemeral"): flavor.add_attr("ephemeral", kwargs.get("ephemeral")) if kwargs.get("is_public"): flavor.add_attr("flavor-access:is_public", kwargs.get("is_public")) flavor.add_attr("xmlns:flavor-access", XMLNS_OS_FLV_ACCESS) resp, body = self.post("flavors", str(Document(flavor)), self.headers) body = xml_to_json(etree.fromstring(body)) flavor = self._format_flavor(body) return resp, flavor
def create_volume_type_extra_specs(self, vol_type_id, extra_spec): """ Creates a new Volume_type extra spec. vol_type_id: Id of volume_type. extra_specs: A dictionary of values to be used as extra_specs. """ url = "types/%s/extra_specs" % str(vol_type_id) extra_specs = Element("extra_specs", xmlns=XMLNS_11) if extra_spec: for key, value in extra_spec.items(): spec = Element('extra_spec') spec.add_attr('key', key) spec.append(Text(value)) extra_specs.append(spec) resp, body = self.post(url, str(Document(extra_specs)), self.headers) body = xml_to_json(etree.fromstring(body)) return resp, body
def update_endpoint(self, endpoint_id, service_id=None, interface=None, url=None, region=None, enabled=None): """Updates an endpoint with given parameters.""" doc = Document() endpoint = Element("endpoint") doc.append(endpoint) if service_id: endpoint.add_attr("service_id", service_id) if interface: endpoint.add_attr("interface", interface) if url: endpoint.add_attr("url", url) if region: endpoint.add_attr("region", region) if enabled is not None: endpoint.add_attr("enabled", enabled) resp, body = self.patch("endpoints/%s" % str(endpoint_id), str(doc), self.headers) body = self._parse_body(etree.fromstring(body)) return resp, body
def _get_element(self, name, value): if value is None: xml_elem = Element(name) xml_elem.add_attr("xsi:nil", "true") return xml_elem elif isinstance(value, dict): dict_element = Element(name) for key, value in value.iteritems(): elem = self._get_element(key, value) dict_element.append(elem) return dict_element elif isinstance(value, list): list_element = Element(name) for element in value: elem = self._get_element(name[:-1], element) list_element.append(elem) return list_element else: return Element(name, value)
def create_flavor(self, name, ram, vcpus, disk, ephemeral, flavor_id, swap, rxtx): """Creates a new flavor or instance type""" flavor = Element("flavor", xmlns=XMLNS_11, ram=ram, vcpus=vcpus, disk=disk, id=flavor_id, swap=swap, rxtx_factor=rxtx, name=name) flavor.add_attr('xmlns:OS-FLV-EXT-DATA', XMLNS_OS_FLV_EXT_DATA) flavor.add_attr('OS-FLV-EXT-DATA:ephemeral', ephemeral) resp, body = self.post('flavors', str(Document(flavor)), self.headers) body = xml_to_json(etree.fromstring(body)) flavor = self._format_flavor(body) return resp, flavor
def update_volume_type_extra_specs(self, vol_type_id, extra_spec_name, extra_spec): """ Update a volume_type extra spec. vol_type_id: Id of volume_type. extra_spec_name: Name of the extra spec to be updated. extra_spec: A dictionary of with key as extra_spec_name and the updated value. """ url = "types/%s/extra_specs/%s" % (str(vol_type_id), str(extra_spec_name)) extra_specs = Element("extra_specs", xmlns=XMLNS_11) if extra_spec is not None: for key, value in extra_spec.items(): spec = Element("extra_spec") spec.add_attr("key", key) spec.append(Text(value)) extra_specs.append(spec) resp, body = self.put(url, str(Document(extra_specs)), self.headers) body = xml_to_json(etree.fromstring(body)) return resp, body
def update_server(self, server_id, name=None, meta=None, accessIPv4=None, accessIPv6=None): doc = Document() server = Element("server") doc.append(server) if name is not None: server.add_attr("name", name) if accessIPv4 is not None: server.add_attr("accessIPv4", accessIPv4) if accessIPv6 is not None: server.add_attr("accessIPv6", accessIPv6) if meta is not None: metadata = Element("metadata") server.append(metadata) for k, v in meta: meta = Element("meta", key=k) meta.append(Text(v)) metadata.append(meta) resp, body = self.put('servers/%s' % str(server_id), str(doc), self.headers) return resp, xml_to_json(etree.fromstring(body))
def rebuild(self, server_id, image_ref, name=None, meta=None, personality=None, adminPass=None, disk_config=None): rebuild = Element("rebuild", xmlns=XMLNS_11, imageRef=image_ref) if name: rebuild.add_attr("name", name) if adminPass: rebuild.add_attr("adminPass", adminPass) if meta: metadata = Element("metadata") rebuild.append(metadata) for k, v in meta.items(): meta = Element("meta", key=k) meta.append(Text(v)) metadata.append(meta) resp, body = self.post('servers/%s/action' % server_id, str(Document(rebuild)), self.headers) server = self._parse_server(etree.fromstring(body)) return resp, server
def update_volume_type_extra_specs(self, vol_type_id, extra_spec_name, extra_spec): """ Update a volume_type extra spec. vol_type_id: Id of volume_type. extra_spec_name: Name of the extra spec to be updated. extra_spec: A dictionary of with key as extra_spec_name and the updated value. """ url = "types/%s/extra_specs/%s" % (str(vol_type_id), str(extra_spec_name)) extra_specs = Element("extra_specs", xmlns=XMLNS_11) if extra_spec is not None: for key, value in extra_spec.items(): spec = Element('extra_spec') spec.add_attr('key', key) spec.append(Text(value)) extra_specs.append(spec) resp, body = self.put(url, str(Document(extra_specs))) body = xml_to_json(etree.fromstring(body)) return resp, body
def create_volume_type_extra_specs(self, vol_type_id, extra_spec): """ Creates a new Volume_type extra spec. vol_type_id: Id of volume_type. extra_specs: A dictionary of values to be used as extra_specs. """ url = "types/%s/extra_specs" % str(vol_type_id) extra_specs = Element("extra_specs", xmlns=XMLNS_11) if extra_spec: if isinstance(extra_spec, list): extra_specs.append(extra_spec) else: for key, value in extra_spec.items(): spec = Element('extra_spec') spec.add_attr('key', key) spec.append(Text(value)) extra_specs.append(spec) else: extra_specs = None resp, body = self.post(url, str(Document(extra_specs))) body = xml_to_json(etree.fromstring(body)) return resp, body
def update_server(self, server_id, name=None, meta=None, accessIPv4=None, accessIPv6=None): doc = Document() server = Element("server") doc.append(server) if name is not None: server.add_attr("name", name) if accessIPv4 is not None: server.add_attr("accessIPv4", accessIPv4) if accessIPv6 is not None: server.add_attr("accessIPv6", accessIPv6) if meta is not None: metadata = Element("metadata") server.append(metadata) for k, v in meta: meta = Element("meta", key=k) meta.append(Text(v)) metadata.append(meta) resp, body = self.put("servers/%s" % str(server_id), str(doc), self.headers) return resp, xml_to_json(etree.fromstring(body))
def create_flavor(self, name, ram, vcpus, disk, flavor_id, **kwargs): """Creates a new flavor or instance type.""" flavor = Element("flavor", xmlns=XMLNS_11, ram=ram, vcpus=vcpus, disk=disk, id=flavor_id, name=name) if kwargs.get('rxtx'): flavor.add_attr('rxtx_factor', kwargs.get('rxtx')) if kwargs.get('swap'): flavor.add_attr('swap', kwargs.get('swap')) if kwargs.get('ephemeral'): flavor.add_attr('OS-FLV-EXT-DATA:ephemeral', kwargs.get('ephemeral')) if kwargs.get('is_public'): flavor.add_attr('os-flavor-access:is_public', kwargs.get('is_public')) flavor.add_attr('xmlns:OS-FLV-EXT-DATA', XMLNS_OS_FLV_EXT_DATA) flavor.add_attr('xmlns:os-flavor-access', XMLNS_OS_FLV_ACCESS) resp, body = self.post('flavors', str(Document(flavor)), self.headers) body = xml_to_json(etree.fromstring(body)) flavor = self._format_flavor(body) return resp, flavor
def update_quota_set(self, tenant_id, force=None, injected_file_content_bytes=None, metadata_items=None, ram=None, floating_ips=None, fixed_ips=None, key_pairs=None, instances=None, security_group_rules=None, injected_files=None, cores=None, injected_file_path_bytes=None, security_groups=None): """ Updates the tenant's quota limits for one or more resources """ post_body = Element("quota_set", xmlns=XMLNS_11) if force is not None: post_body.add_attr('force', force) if injected_file_content_bytes is not None: post_body.add_attr('injected_file_content_bytes', injected_file_content_bytes) if metadata_items is not None: post_body.add_attr('metadata_items', metadata_items) if ram is not None: post_body.add_attr('ram', ram) if floating_ips is not None: post_body.add_attr('floating_ips', floating_ips) if fixed_ips is not None: post_body.add_attr('fixed_ips', fixed_ips) if key_pairs is not None: post_body.add_attr('key_pairs', key_pairs) if instances is not None: post_body.add_attr('instances', instances) if security_group_rules is not None: post_body.add_attr('security_group_rules', security_group_rules) if injected_files is not None: post_body.add_attr('injected_files', injected_files) if cores is not None: post_body.add_attr('cores', cores) if injected_file_path_bytes is not None: post_body.add_attr('injected_file_path_bytes', injected_file_path_bytes) if security_groups is not None: post_body.add_attr('security_groups', security_groups) resp, body = self.put('os-quota-sets/%s' % str(tenant_id), str(Document(post_body)), self.headers) body = xml_to_json(etree.fromstring(body)) body = self._format_quota(body) return resp, body