| # Copyright 2017-present Open Networking Foundation |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| from xosapi.orm import ORMWrapper, register_convenience_wrapper |
| |
| |
| class ORMWrapperService(ORMWrapper): |
| @property |
| def serviceattribute_dict(self): |
| attrs = {} |
| for attr in self.serviceattributes.all(): |
| attrs[attr.name] = attr.value |
| return attrs |
| |
| def get_composable_networks(self): |
| SUPPORTED_VTN_SERVCOMP_KINDS = ["VSG", "PRIVATE"] |
| |
| nets = [] |
| for slice in self.slices.all(): |
| for net in slice.networks.all(): |
| if (net.template.vtn_kind not in SUPPORTED_VTN_SERVCOMP_KINDS) or ( |
| net.owner.id != slice.id |
| ): |
| continue |
| |
| if not net.controllernetworks.exists(): |
| continue |
| nets.append(net) |
| return nets |
| |
| def get_service_instance_class_name(self): |
| # This assumes that a ServiceInstance is always named after its service. For example |
| # VSGService --> VSGServiceInstance. Services in which this is not the case should override this method. |
| # TODO: Specify via xproto ? |
| return self.leaf_model_name + "Instance" |
| |
| def get_service_instance_class(self): |
| return getattr(self.stub, self.get_service_instance_class_name()) |
| |
| @property |
| def provider_services(self): |
| svcs = [] |
| service_deps = self.subscribed_dependencies.all() |
| for dep in service_deps: |
| svcs.append(dep.provider_service) |
| return svcs |
| |
| @property |
| def subscriber_services(self): |
| svcs = [] |
| service_deps = self.provided_dependencies.all() |
| for dep in service_deps: |
| svcs.append(dep.subscriber_service) |
| return svcs |
| |
| def acquire_service_instance(self, subscriber_service_instance): |
| """ Given a subscriber_service_instance: |
| 1) If there is an eligible provider_service_instance that can be used, then link to it |
| 2) Otherwise, create a new provider_service_instance and link to it. |
| |
| This is the base class, knows nothing of service specifics, so it assumes that #1 always yields no |
| eligible provider_service_instances. To get custom behavior, override this method in your own |
| convenience wrapper. |
| """ |
| si_classname = self.get_service_instance_class_name() |
| |
| ServiceInstanceLink = self.stub.ServiceInstanceLink |
| |
| eastbound_si_class = getattr(self.stub, si_classname) |
| eastbound_si = eastbound_si_class(owner_id=self.id) |
| eastbound_si.save() |
| |
| link = ServiceInstanceLink( |
| provider_service_instance=eastbound_si, |
| subscriber_service_instance=subscriber_service_instance, |
| ) |
| link.save() |
| |
| def validate_links(self, subscriber_service_instance): |
| """ Validate existing links between the provider and subscriber service instances. If a valid link exists, |
| then return it. Return [] otherwise. |
| |
| This is the base class, knows nothing of service specifics, so it assumes that all existing links are |
| valid. To get custom behavior, override this method in your own convenience wrapper. |
| """ |
| matched = [] |
| for link in subscriber_service_instance.subscribed_links.all(): |
| if link.provider_service_instance.owner.id == self.id: |
| matched.append(link.provider_service_instance.leaf_model) |
| return matched |
| |
| |
| register_convenience_wrapper("Service", ORMWrapperService) |