def create(self, req, body): parser = req.get_parser()(req.headers, req.body) scheme = { "category": compute.ComputeResource.kind, "mixins": [ templates.OpenStackOSTemplate, templates.OpenStackResourceTemplate, ], "optional_mixins": [ contextualization.user_data, contextualization.public_key, ] } obj = parser.parse() validator = occi_validator.Validator(obj) validator.validate(scheme) attrs = obj.get("attributes", {}) name = attrs.get("occi.core.title", "OCCI_VM") image = obj["schemes"][templates.OpenStackOSTemplate.scheme][0] flavor = obj["schemes"][templates.OpenStackResourceTemplate.scheme][0] user_data, key_name, key_data = None, None, None create_key, create_key_tmp = False, False if contextualization.user_data.scheme in obj["schemes"]: user_data = attrs.get("org.openstack.compute.user_data") if contextualization.public_key.scheme in obj["schemes"]: key_name = attrs.get("org.openstack.credentials.publickey.name") key_data = attrs.get("org.openstack.credentials.publickey.data") if key_name and key_data: create_key = True elif not key_name and key_data: # NOTE(orviz) To be occi-os compliant, not # raise exception.MissingKeypairName key_name = uuid.uuid4().hex create_key = True create_key_tmp = True if create_key: # add keypair: if key_name already exists, a 409 HTTP code # will be returned by OpenStack self.os_helper.keypair_create(req, key_name, public_key=key_data) server = self.os_helper.create_server(req, name, image, flavor, user_data=user_data, key_name=key_name) # The returned JSON does not contain the server name server["name"] = name occi_compute_resources = self._get_compute_resources([server]) if create_key_tmp: self.os_helper.keypair_delete(req, key_name) return collection.Collection(resources=occi_compute_resources)
def run_action(self, req, id, body): action = req.GET.get("action", None) occi_actions = [a.term for a in compute.ComputeResource.actions] if action is None or action not in occi_actions: raise exception.InvalidAction(action=action) parser = req.get_parser()(req.headers, req.body) obj = parser.parse() server = self.os_helper.get_server(req, id) if action == "stop": scheme = {"category": compute.stop} elif action == "start": scheme = {"category": compute.start} if server["status"] == "SUSPENDED": action = "resume" elif server["status"] == "PAUSED": action = "unpause" elif action == "restart": scheme = {"category": compute.restart} elif action == "suspend": scheme = {"category": compute.suspend} else: raise exception.NotImplemented validator = occi_validator.Validator(obj) validator.validate(scheme) self.os_helper.run_action(req, action, id) return []
def create(self, req, body=None): """Create a security group link Creates a link between a server and a securitygroup. :param req: request object :param body: body request (not used) """ parser = req.get_parser()(req.headers, req.body) scheme = { "category": securitygroup_link.SecurityGroupLink.kind, } obj = parser.parse() validator = occi_validator.Validator(obj) validator.validate(scheme) attrs = obj.get("attributes", {}) _, securitygroup_id = ooi.api.helpers.get_id_with_kind( req, attrs.get("occi.core.target"), securitygroup.SecurityGroupResource.kind) _, server_id = ooi.api.helpers.get_id_with_kind( req, attrs.get("occi.core.source"), compute.ComputeResource.kind) self.os_helper.create_server_security_link(req, server_id, securitygroup_id) link = { "compute_id": server_id, "securitygroup": { "id": securitygroup_id } } occi_instance = _get_security_link_resources([link]) return collection.Collection(resources=occi_instance)
def create(self, req, body): parser = req.get_parser()(req.headers, req.body) scheme = {"category": network_link.NetworkInterface.kind} obj = parser.parse() validator = occi_validator.Validator(obj) validator.validate(scheme) attrs = obj.get("attributes", {}) server_id = attrs.get("occi.core.source") net_id = attrs.get("occi.core.target") # net_id is something like "fixed" or "floating/<pool_name>" if net_id == "fixed": raise exception.Invalid() try: _, pool_name = net_id.split("/", 1) except ValueError: raise exception.NetworkPoolFound(pool=net_id) # Allocate IP ip = self.os_helper.allocate_floating_ip(req, pool_name) # Add it to server self.os_helper.associate_floating_ip(req, server_id, ip["id"]) n = network.NetworkResource(title="network", id=net_id) c = compute.ComputeResource(title="Compute", id=server_id) l = os_network.OSNetworkInterface(c, n, "mac", ip["ip"]) return collection.Collection(resources=[l])
def test_something_unexpected(self): mixins = collections.Counter() schemes = collections.defaultdict(list) mixins["http://example.com/scheme#foo"] += 1 schemes["http://example.com/scheme#"].append("foo") pobj = { "kind": "compute", "category": "foo type", "mixins": mixins, "schemes": schemes, } v = validator.Validator(pobj) self.assertRaises(exception.OCCISchemaMismatch, v.validate, {})
def test_missing_category(self): mixins = collections.Counter() schemes = collections.defaultdict(list) pobj = { "kind": "compute", "mixins": mixins, "schemes": schemes, } cat = mock.MagicMock() cat.type_id = "foo type" scheme = {"category": cat} v = validator.Validator(pobj) self.assertRaises(exception.OCCIMissingType, v.validate, scheme)
def test_optional_links_invalid(self): mixins = collections.Counter() schemes = collections.defaultdict(list) links = {"http://example.com/scheme#foo": [{"location": "foo"}]} pobj = { "kind": "compute", "category": "foo type", "mixins": mixins, "schemes": schemes, "links": links } link = mock.MagicMock() link.type_id = "http://example.com/scheme#foo" scheme = {"optional_links": []} v = validator.Validator(pobj) self.assertRaises(exception.OCCISchemaMismatch, v.validate, scheme)
def test_category(self): mixins = collections.Counter() schemes = collections.defaultdict(list) pobj = { "kind": "compute", "category": "foo type", "mixins": mixins, "schemes": schemes, } cat = mock.MagicMock() cat.type_id = "foo type" scheme = {"category": cat} v = validator.Validator(pobj) self.assertTrue(v.validate(scheme))
def test_optional_links(self): mixins = collections.Counter() schemes = collections.defaultdict(list) links = {"http://example.com/scheme#foo": [{"location": "foo"}]} pobj = { "kind": "compute", "category": "foo type", "mixins": mixins, "schemes": schemes, "links": links } link = mock.MagicMock() link.type_id = "http://example.com/scheme#foo" scheme = {"optional_links": [link]} v = validator.Validator(pobj) self.assertTrue(v.validate(scheme))
def test_no_optional_mixins(self): mixins = collections.Counter() schemes = collections.defaultdict(list) pobj = { "kind": "compute", "category": "foo type", "mixins": mixins, "schemes": schemes, } mixin = mock.MagicMock() mixin.scheme = "http://example.com/scheme#" mixin.term = "foo" scheme = {"optional_mixins": [mixin]} v = validator.Validator(pobj) self.assertTrue(v.validate(scheme))
def test_mixin_schema_mismatch_term(self): mixins = collections.Counter() schemes = collections.defaultdict(list) mixins["http://example.com/scheme#foo"] += 1 schemes["http://example.com/scheme#"].append("foo") pobj = { "kind": "compute", "category": "foo type", "mixins": mixins, "schemes": schemes, } mixin = mock.MagicMock() mixin.scheme = "http://example.com/scheme#" mixin.term = "bar" scheme = {"mixins": [mixin]} v = validator.Validator(pobj) self.assertRaises(exception.OCCIMissingType, v.validate, scheme)
def create(self, req, body): parser = req.get_parser()(req.headers, req.body) scheme = {"category": storage_link.StorageLink.kind} obj = parser.parse() validator = occi_validator.Validator(obj) validator.validate(scheme) attrs = obj.get("attributes", {}) vol_id = attrs.get("occi.core.target") server_id = attrs.get("occi.core.source") device = attrs.get("occi.storagelink.deviceid", None) attachment = self.os_helper.create_server_volumes_link(req, server_id, vol_id, dev=device) c = compute.ComputeResource(title="Compute", id=server_id) s = storage.StorageResource(title="Storage", id=vol_id) l = storage_link.StorageLink(c, s, deviceid=attachment["device"]) return collection.Collection(resources=[l])
def parse_validate_schema(req, scheme=None, required_attr=None): """Parse attributes and validate scheme Returns attributes from request If scheme is specified, it validates the OCCI scheme: -Raises exception in case of being invalid :param req: request :param: scheme: scheme to validate :param: required_attr: attributes required """ parser = req.get_parser()(req.headers, req.body.decode("utf8")) if scheme: attributes = parser.parse() validator = occi_validator.Validator(attributes) validator.validate(scheme) validator.validate_attributes(required_attr) else: attributes = parser.parse_attributes(req.headers) return attributes
def create(self, req, body): parser = req.get_parser()(req.headers, req.body) scheme = { "category": network_link.NetworkInterface.kind, "optional_mixins": [ os_network.OSFloatingIPPool, ] } obj = parser.parse() validator = occi_validator.Validator(obj) validator.validate(scheme) attrs = obj.get("attributes", {}) _, net_id = helpers.get_id_with_kind( req, attrs.get("occi.core.target"), network.NetworkResource.kind) _, server_id = helpers.get_id_with_kind( req, attrs.get("occi.core.source"), compute.ComputeResource.kind) # net_id is something like "fixed" or "floating" if net_id == network_api.FIXED_PREFIX: raise exception.Invalid() elif net_id != network_api.FLOATING_PREFIX: raise exception.NetworkNotFound(resource_id=net_id) pool_name = None if os_network.OSFloatingIPPool.scheme in obj["schemes"]: pool_name = obj["schemes"][os_network.OSFloatingIPPool.scheme][0] # Allocate IP ip = self.os_helper.allocate_floating_ip(req, pool_name) # Add it to server self.os_helper.associate_floating_ip(req, server_id, ip["ip"]) n = network.NetworkResource(title="network", id=net_id) c = compute.ComputeResource(title="Compute", id=server_id) l = os_network.OSNetworkInterface(c, n, "mac", ip["ip"]) return collection.Collection(resources=[l])
def create(self, req, body): parser = req.get_parser()(req.headers, req.body) scheme = {"category": storage.StorageResource.kind} obj = parser.parse() validator = occi_validator.Validator(obj) validator.validate(scheme) attrs = obj.get("attributes", {}) name = attrs.get("occi.core.title", "OCCI Volume") # TODO(enolfc): this should be handled by the validator try: size = attrs["occi.storage.size"] except KeyError: raise exception.Invalid() volume = self.os_helper.volume_create(req, name, size) st = storage.StorageResource(title=volume["displayName"], id=volume["id"], size=volume["size"], state=helpers.vol_state(volume["status"])) return collection.Collection(resources=[st])
def create(self, req, body=None): """Create an ip reservation instance in the cloud :param req: request object :param body: body request (not used) """ parser = req.get_parser()(req.headers, req.body) scheme = { "category": ip_reservation.IPReservation.kind, "optional_mixins": [ os_network.OSFloatingIPPool, ] } obj = parser.parse() validator = occi_validator.Validator(obj) validator.validate(scheme) pool = None if os_network.OSFloatingIPPool.scheme in obj["schemes"]: pool = (obj["schemes"][os_network.OSFloatingIPPool.scheme][0]) resp = self.os_helper.allocate_floating_ip(req, pool) occi_network_resources = self._get_ipreservation_resources([resp]) return collection.Collection(resources=occi_network_resources)
def create(self, req, body=None): """Create a networkLink Creates a link between a server and a network. It could be fixed or floating IP. :param req: request object :param body: body request (not used) """ parser = req.get_parser()(req.headers, req.body) scheme = { "category": network_link.NetworkInterface.kind, "optional_mixins": [ os_network.OSFloatingIPPool, ] } obj = parser.parse() validator = occi_validator.Validator(obj) validator.validate(scheme) attrs = obj.get("attributes", {}) _, net_id = helpers.get_id_with_kind(req, attrs.get("occi.core.target"), network.NetworkResource.kind) _, server_id = helpers.get_id_with_kind(req, attrs.get("occi.core.source"), compute.ComputeResource.kind) pool = None if os_network.OSFloatingIPPool.scheme in obj["schemes"]: pool = (obj["schemes"][os_network.OSFloatingIPPool.scheme][0]) # Allocate public IP and associate it ot the server if net_id == os_helpers.PUBLIC_NETWORK: os_link = self.os_helper.assign_floating_ip( req, net_id, server_id, pool) else: # Allocate private network os_link = self.os_helper.create_port(req, net_id, server_id) occi_link = _get_network_link_resources([os_link]) return collection.Collection(resources=occi_link)
def create(self, req, body): parser = req.get_parser()(req.headers, req.body) scheme = { "category": compute.ComputeResource.kind, "mixins": [ templates.OpenStackOSTemplate, templates.OpenStackResourceTemplate, ], "optional_mixins": [ contextualization.user_data, contextualization.ssh_key, os_contextualization.user_data, os_contextualization.public_key, ], "optional_links": [ storage.StorageResource.kind, network.NetworkResource.kind, ] } obj = parser.parse() validator = occi_validator.Validator(obj) validator.validate(scheme) attrs = obj.get("attributes", {}) name = attrs.get("occi.core.title", "OCCI_VM") image = obj["schemes"][templates.OpenStackOSTemplate.scheme][0] flavor = obj["schemes"][templates.OpenStackResourceTemplate.scheme][0] user_data, key_name, key_data = None, None, None create_key, create_key_tmp = False, False # TODO(enolfc): deprecate OS Contextualization in the future # meanwhile, raise 409 conflict if both contextualizations types appear if (os_contextualization.user_data.scheme in obj["schemes"] and contextualization.user_data.scheme in obj["schemes"]): raise exception.OCCIMixinConflict() if os_contextualization.user_data.scheme in obj["schemes"]: user_data = attrs.get("org.openstack.compute.user_data") if contextualization.user_data.scheme in obj["schemes"]: user_data = attrs.get("occi.compute.user_data") if (os_contextualization.public_key.scheme in obj["schemes"] and contextualization.ssh_key.scheme in obj["schemes"]): raise exception.OCCIMixinConflict() key_name = key_data = None if os_contextualization.public_key.scheme in obj["schemes"]: key_name = attrs.get("org.openstack.credentials.publickey.name") key_data = attrs.get("org.openstack.credentials.publickey.data") if contextualization.ssh_key.scheme in obj["schemes"]: if key_data or key_name: raise exception.OCCIMixinConflict() key_data = attrs.get("occi.credentials.ssh_key") if key_name and key_data: create_key = True elif not key_name and key_data: # NOTE(orviz) To be occi-os compliant, not # raise exception.MissingKeypairName key_name = uuid.uuid4().hex create_key = True create_key_tmp = True if create_key: # add keypair: if key_name already exists, a 409 HTTP code # will be returned by OpenStack self.os_helper.keypair_create(req, key_name, public_key=key_data) block_device_mapping_v2 = self._build_block_mapping(req, obj) networks = self._get_network_from_req(req, obj) server = self.os_helper.create_server( req, name, image, flavor, user_data=user_data, key_name=key_name, block_device_mapping_v2=block_device_mapping_v2, networks=networks) # The returned JSON does not contain the server name server["name"] = name occi_compute_resources = self._get_compute_resources([server]) if create_key_tmp: self.os_helper.keypair_delete(req, key_name) return collection.Collection(resources=occi_compute_resources)