##
# Yang targets
##
+
+ rift_add_yang_target(
+ TARGET rwsdn_yang
+ YANG_FILES rw-sdn.yang
+ COMPONENT ${PKG_LONG_NAME}
+ LIBRARIES
+ rwsdnal_yang_gen
+ DEPENDS
+ rwsdnal_yang
++ ASSOCIATED_FILES
++ rw-sdn.role.xml
+ )
+
rift_add_yang_target(
TARGET rwcloud_yang
- YANG_FILES rw-cloud.yang rw-sdn.yang
+ YANG_FILES rw-cloud.yang
COMPONENT ${PKG_LONG_NAME}
LIBRARIES
rwsdn_yang_gen
rwcal_yang_gen
+ rwprojectmano_yang_gen
+ mano-types_yang_gen
DEPENDS
rwcal_yang
- rwsdn_yang
- rwprojectmano_yang
- mano-types_yang
+ rwsdnal_yang
+ ASSOCIATED_FILES
+ rw-cloud.role.xml
- rw-sdn.role.xml
)
rift_add_yang_target(
prefix "rwpb";
}
- import mano-types {
- prefix "manotypes";
- }
-
+ import rw-project {
+ prefix "rw-project";
+ }
+
- import rwsdn {
- prefix "rwsdn";
+ import rwsdnal {
+ prefix "rwsdnal";
+ }
+
++ import mano-types {
++ prefix "manotypes";
+ }
+
+ revision 2017-02-08 {
+ description
+ "Update model to support projects.";
+ }
+
revision 2015-09-14 {
description
"Initial revision.";
}
- augment "/rw-project:project" {
- container sdn {
++augment "/rw-project:project" {
+ container sdn {
- rwpb:msg-new SDNAccountConfig;
- list account {
- rwpb:msg-new SDNAccount;
- key "name";
- leaf name {
- type string;
- }
++ rwpb:msg-new SDNAccountConfig;
+ list account {
- rwpb:msg-new SDNAccountConfig;
++ rwpb:msg-new SDNAccount;
+ key "name";
+ leaf name {
- type string;
++ type string;
+ }
- uses rwsdn:sdn-provider-auth;
- uses rwsdn:connection-status;
- uses rwsdnal:sdn-provider-auth;
- uses rwsdnal:connection-status;
++ uses rwsdnal:sdn-provider-auth;
++ uses rwsdnal:connection-status;
+ }
}
}
--- /dev/null
-def get_add_delete_update_cfgs(dts_member_reg, xact, key_name):
- # Unforunately, it is currently difficult to figure out what has exactly
- # changed in this xact without Pbdelta support (RIFT-4916)
- # As a workaround, we can fetch the pre and post xact elements and
- # perform a comparison to figure out adds/deletes/updates
- xact_cfgs = list(dts_member_reg.get_xact_elements(xact))
- curr_cfgs = list(dts_member_reg.elements)
-
- xact_key_map = {getattr(cfg, key_name): cfg for cfg in xact_cfgs}
- curr_key_map = {getattr(cfg, key_name): cfg for cfg in curr_cfgs}
-
- # Find Adds
- added_keys = set(xact_key_map) - set(curr_key_map)
- added_cfgs = [xact_key_map[key] for key in added_keys]
-
- # Find Deletes
- deleted_keys = set(curr_key_map) - set(xact_key_map)
- deleted_cfgs = [curr_key_map[key] for key in deleted_keys]
-
- # Find Updates
- updated_keys = set(curr_key_map) & set(xact_key_map)
- updated_cfgs = [xact_key_map[key] for key in updated_keys if xact_key_map[key] != curr_key_map[key]]
-
- return added_cfgs, deleted_cfgs, updated_cfgs
-
-
+
+ #
+ # Copyright 2017 RIFT.IO Inc
+ #
+ # 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.
+ #
+
+ import asyncio
+
+ import gi
+ gi.require_version('RwDts', '1.0')
+ import rift.tasklets
+
+ from gi.repository import (
+ RwDts as rwdts,
+ ProtobufC,
+ )
+
++from rift.mano.utils.project import get_add_delete_update_cfgs
++
+ from . import accounts
+
+
+ class SDNAccountNotFound(Exception):
+ pass
+
+
+ class SDNAccountError(Exception):
+ pass
+
+
+ class SDNAccountConfigCallbacks(object):
+ def __init__(self,
+ on_add_apply=None, on_add_prepare=None,
+ on_delete_apply=None, on_delete_prepare=None):
+
+ @asyncio.coroutine
+ def prepare_noop(*args, **kwargs):
+ pass
+
+ def apply_noop(*args, **kwargs):
+ pass
+
+ self.on_add_apply = on_add_apply
+ self.on_add_prepare = on_add_prepare
+ self.on_delete_apply = on_delete_apply
+ self.on_delete_prepare = on_delete_prepare
+
+ for f in ('on_add_apply', 'on_delete_apply'):
+ ref = getattr(self, f)
+ if ref is None:
+ setattr(self, f, apply_noop)
+ continue
+
+ if asyncio.iscoroutinefunction(ref):
+ raise ValueError('%s cannot be a coroutine' % (f,))
+
+ for f in ('on_add_prepare', 'on_delete_prepare'):
+ ref = getattr(self, f)
+ if ref is None:
+ setattr(self, f, prepare_noop)
+ continue
+
+ if not asyncio.iscoroutinefunction(ref):
+ raise ValueError("%s must be a coroutine" % f)
+
+
+ class SDNAccountConfigSubscriber(object):
+ XPATH = "C,/rw-sdn:sdn/rw-sdn:account"
+
+ def __init__(self, dts, log, rwlog_hdl, sdn_callbacks, acctstore):
+ self._dts = dts
+ self._log = log
+ self._rwlog_hdl = rwlog_hdl
+ self._reg = None
+
+ self.accounts = acctstore
+
+ self._sdn_callbacks = sdn_callbacks
+
+ def add_account(self, account_msg):
+ self._log.info("adding sdn account: {}".format(account_msg))
+
+ account = accounts.SDNAccount(self._log, self._rwlog_hdl, account_msg)
+ self.accounts[account.name] = account
+
+ self._sdn_callbacks.on_add_apply(account)
+
+ def delete_account(self, account_name):
+ self._log.info("deleting sdn account: {}".format(account_name))
+ del self.accounts[account_name]
+
+ self._sdn_callbacks.on_delete_apply(account_name)
+
+ def update_account(self, account_msg):
+ """ Update an existing sdn account
+
+ In order to simplify update, turn an update into a delete followed by
+ an add. The drawback to this approach is that we will not support
+ updates of an "in-use" sdn account, but this seems like a
+ reasonable trade-off.
+
+
+ Arguments:
+ account_msg - The sdn account config message
+ """
+ self._log.info("updating sdn account: {}".format(account_msg))
+
+ self.delete_account(account_msg.name)
+ self.add_account(account_msg)
+
++ def deregister(self):
++ if self._reg:
++ self._reg.deregister()
++ self._reg = None
++
+ def register(self):
+ @asyncio.coroutine
+ def apply_config(dts, acg, xact, action, _):
+ self._log.debug("Got sdn account apply config (xact: %s) (action: %s)", xact, action)
+
+ if xact.xact is None:
+ if action == rwdts.AppconfAction.INSTALL:
+ curr_cfg = self._reg.elements
+ for cfg in curr_cfg:
+ self._log.debug("SDN account being re-added after restart.")
+ if not cfg.has_field('account_type'):
+ raise SDNAccountError("New SDN account must contain account_type field.")
+ self.add_account(cfg)
+ else:
+ # When RIFT first comes up, an INSTALL is called with the current config
+ # Since confd doesn't actally persist data this never has any data so
+ # skip this for now.
+ self._log.debug("No xact handle. Skipping apply config")
+
+ return
+
+ add_cfgs, delete_cfgs, update_cfgs = get_add_delete_update_cfgs(
+ dts_member_reg=self._reg,
+ xact=xact,
+ key_name="name",
+ )
+
+ # Handle Deletes
+ for cfg in delete_cfgs:
+ self.delete_account(cfg.name)
+
+ # Handle Adds
+ for cfg in add_cfgs:
+ self.add_account(cfg)
+
+ # Handle Updates
+ for cfg in update_cfgs:
+ self.update_account(cfg)
+
+ @asyncio.coroutine
+ def on_prepare(dts, acg, xact, xact_info, ks_path, msg, scratch):
+ """ Prepare callback from DTS for SDN Account """
+
+ action = xact_info.query_action
+ self._log.debug("SDN account on_prepare config received (action: %s): %s",
+ xact_info.query_action, msg)
+
+ if action in [rwdts.QueryAction.CREATE, rwdts.QueryAction.UPDATE]:
+ if msg.name in self.accounts:
+ self._log.debug("SDN account already exists. Invoking update request")
+
+ # Since updates are handled by a delete followed by an add, invoke the
+ # delete prepare callbacks to give clients an opportunity to reject.
+ yield from self._sdn_callbacks.on_delete_prepare(msg.name)
+
+ else:
+ self._log.debug("SDN account does not already exist. Invoking on_prepare add request")
+ if not msg.has_field('account_type'):
+ raise SDNAccountError("New sdn account must contain account_type field.")
+
+ account = accounts.SDNAccount(self._log, self._rwlog_hdl, msg)
+ yield from self._sdn_callbacks.on_add_prepare(account)
+
+ elif action == rwdts.QueryAction.DELETE:
+ # Check if the entire SDN account got deleted
+ fref = ProtobufC.FieldReference.alloc()
+ fref.goto_whole_message(msg.to_pbcm())
+ if fref.is_field_deleted():
+ yield from self._sdn_callbacks.on_delete_prepare(msg.name)
+
+ else:
+ self._log.error("Deleting individual fields for SDN account not supported")
+ xact_info.respond_xpath(rwdts.XactRspCode.NACK)
+ return
+
+ else:
+ self._log.error("Action (%s) NOT SUPPORTED", action)
+ xact_info.respond_xpath(rwdts.XactRspCode.NACK)
+
+ xact_info.respond_xpath(rwdts.XactRspCode.ACK)
+
+ self._log.debug("Registering for SDN Account config using xpath: %s",
+ SDNAccountConfigSubscriber.XPATH,
+ )
+
+ acg_handler = rift.tasklets.AppConfGroup.Handler(
+ on_apply=apply_config,
+ )
+
+ with self._dts.appconf_group_create(acg_handler) as acg:
+ self._reg = acg.register(
+ xpath=SDNAccountConfigSubscriber.XPATH,
+ flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY | rwdts.Flag.CACHE,
+ on_prepare=on_prepare,
+ )
--- /dev/null
- yield from self._dts.register(
+
+ #
+ # Copyright 2017 RIFT.IO Inc
+ #
+ # 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.
+ #
+
+ import asyncio
+ import rift.tasklets
+
+ from gi.repository import(
+ RwSdnYang,
+ RwDts as rwdts,
+ )
+
+
+ class SDNAccountNotFound(Exception):
+ pass
+
+
+ class SDNAccountDtsOperdataHandler(object):
+ def __init__(self, dts, log, loop):
+ self._dts = dts
+ self._log = log
+ self._loop = loop
+
+ self.sdn_accounts = {}
++ self._oper = None
++ self._rpc = None
+
+ def add_sdn_account(self, account):
+ self.sdn_accounts[account.name] = account
+ account.start_validate_credentials(self._loop)
+
+ def delete_sdn_account(self, account_name):
+ del self.sdn_accounts[account_name]
+
+ def get_saved_sdn_accounts(self, sdn_account_name):
+ ''' Get SDN Account corresponding to passed name, or all saved accounts if name is None'''
+ saved_sdn_accounts = []
+
+ if sdn_account_name is None or sdn_account_name == "":
+ sdn_accounts = list(self.sdn_accounts.values())
+ saved_sdn_accounts.extend(sdn_accounts)
+ elif sdn_account_name in self.sdn_accounts:
+ account = self.sdn_accounts[sdn_account_name]
+ saved_sdn_accounts.append(account)
+ else:
+ errstr = "SDN account {} does not exist".format(sdn_account_name)
+ raise KeyError(errstr)
+
+ return saved_sdn_accounts
+
+ def _register_show_status(self):
+ def get_xpath(sdn_name=None):
+ return "D,/rw-sdn:sdn/account{}/connection-status".format(
+ "[name='%s']" % sdn_name if sdn_name is not None else ''
+ )
+
+ @asyncio.coroutine
+ def on_prepare(xact_info, action, ks_path, msg):
+ self._log.debug("Got show SDN connection status request: %s", ks_path.create_string())
+ path_entry = RwSdnYang.SDNAccount.schema().keyspec_to_entry(ks_path)
+ sdn_account_name = path_entry.key00.name
+
+ try:
+ saved_accounts = self.get_saved_sdn_accounts(sdn_account_name)
+ for account in saved_accounts:
+ connection_status = account.connection_status
+ self._log.debug("Responding to SDN connection status request: %s", connection_status)
+ xact_info.respond_xpath(
+ rwdts.XactRspCode.MORE,
+ xpath=get_xpath(account.name),
+ msg=account.connection_status,
+ )
+ except KeyError as e:
+ self._log.warning(str(e))
+ xact_info.respond_xpath(rwdts.XactRspCode.NA)
+ return
+
+ xact_info.respond_xpath(rwdts.XactRspCode.ACK)
+
- yield from self._dts.register(
- xpath=get_xpath(),
- handler=rift.tasklets.DTS.RegistrationHandler(
- on_prepare=on_prepare
- ),
- flags=rwdts.Flag.PUBLISHER,
- )
++ self._oper = yield from self._dts.register(
+ xpath=get_xpath(),
+ handler=rift.tasklets.DTS.RegistrationHandler(
+ on_prepare=on_prepare),
+ flags=rwdts.Flag.PUBLISHER,
+ )
+
+ def _register_validate_rpc(self):
+ def get_xpath():
+ return "/rw-sdn:update-sdn-status"
+
+ @asyncio.coroutine
+ def on_prepare(xact_info, action, ks_path, msg):
++ if self._project and not self._project.rpc_check(msg, xact_info=xact_info):
++ return
++
+ if not msg.has_field("sdn_account"):
+ raise SDNAccountNotFound("SDN account name not provided")
+
+ sdn_account_name = msg.sdn_account
+ try:
+ account = self.sdn_accounts[sdn_account_name]
+ except KeyError:
+ raise SDNAccountNotFound("SDN account name %s not found" % sdn_account_name)
+
+ account.start_validate_credentials(self._loop)
+
+ xact_info.respond_xpath(rwdts.XactRspCode.ACK)
+
++ self._rpc = yield from self._dts.register(
++ xpath=get_xpath(),
++ handler=rift.tasklets.DTS.RegistrationHandler(
++ on_prepare=on_prepare
++ ),
++ flags=rwdts.Flag.PUBLISHER,
++ )
+
+ @asyncio.coroutine
+ def register(self):
+ yield from self._register_show_status()
+ yield from self._register_validate_rpc()
++
++ def deregister(self):
++ if self._oper:
++ self._oper.deregister()
++ self._oper = None
++
++ if self._rpc:
++ self._rpc.deregister()
++ self._rpc = None
rwcloud_yang_gen
rwconfig_agent_yang_gen
mano-types_yang_gen
+ rwprojectmano_yang_gen
DEPENDS
rwcloud_yang
++ rwsdn_yang
rwconfig_agent_yang
+ rwprojectmano_yang
+ ASSOCIATED_FILES
+ project-vnfd.role.xml
+ project-nsd.role.xml
+ vnfr.role.xml
+ rw-vnfr.role.xml
+ vlr.role.xml
+ nsr.role.xml
)
#rift_gen_yang_tree(mano-pyang-trees
}
}
- rpc start-network-service {
- description "Start the network service";
- input {
+ grouping cloud-config {
+ description "List of cloud config parameters";
+
+ list ssh-authorized-key {
+ key "key-pair-ref";
+
+ description "List of authorized ssh keys as part of cloud-config";
+
+ leaf key-pair-ref {
+ description "A reference to the key pair entry in the global key pair table";
+ type leafref {
+ path "/nsr:key-pair/nsr:name";
+ }
+ }
+ }
+ list user {
+ key "name";
+
+ description "List of users to be added through cloud-config";
+ leaf name {
+ description "Name of the user ";
+ type string;
+ }
+ leaf user-info {
+ description "The user name's real name";
+ type string;
+ }
+ list ssh-authorized-key {
+ key "key-pair-ref";
+
+ description "Used to configure the list of public keys to be injected as part
+ of ns instantiation";
+
+ leaf key-pair-ref {
+ description "A reference to the key pair entry in the global key pair table";
+ type leafref {
+ path "/nsr:key-pair/nsr:name";
+ }
+ }
+ }
+ }
+ }
+
+ list key-pair {
+ key "name";
+ description "Used to configure the list of public keys to be injected as part
+ of ns instantiation";
+ leaf name {
+ description "Name of this key pair";
+ type string;
+ }
+
+ leaf key {
+ description "Key associated with this key pair";
+ type string;
+ }
+ }
+
+ augment "/rw-project:project" {
+ list key-pair {
+ key "name";
+ description "Used to configure the list of public keys to be injected as part
+ of ns instantiation";
leaf name {
- mandatory true;
- description "Name of the Network Service";
+ description "Name of this key pair";
type string;
}
- leaf nsd-ref {
- description "Reference to NSR ID ref";
- mandatory true;
- type leafref {
- path "/nsd:nsd-catalog/nsd:nsd/nsd:id";
- }
- }
- uses ns-instance-config-params;
- }
- output {
- leaf nsr-id {
- description "Automatically generated parameter";
- type yang:uuid;
+ leaf key {
+ description "Key associated with this key pair";
+ type string;
}
}
}
NOTE: An issue with confd is preventing the
use of xpath. Seems to be an issue with leafref
to leafref, whose target is in a different module.
- Once that is resovled this will switched to use
+ Once that is resolved this will switched to use
leafref";
- type yang:uuid;
- }
+ type yang:uuid;
+ }
- leaf placement-group-ref {
- description
+ leaf placement-group-ref {
+ description
"A reference to VNFD placement group";
- type leafref {
- path "/vnfd:vnfd-catalog/vnfd:vnfd[vnfd:id = current()/" +
- "../nsr:vnfd-id-ref]/vnfd:placement-groups/vnfd:name";
+ type leafref {
+ path "../../../../project-vnfd:vnfd-catalog/project-vnfd:vnfd[project-vnfd:id = " +
+ "current()/../vnfd-id-ref]/project-vnfd:placement-groups/project-vnfd:name";
+ }
}
+
+ uses manotypes:placement-group-input;
}
- list ssh-authorized-key {
- key "key-pair-ref";
-
- description "List of authorized ssh keys as part of cloud-config";
-
- leaf key-pair-ref {
- description "A reference to the key pair entry in the global key pair table";
- type leafref {
- path "../../../../key-pair/name";
- }
- }
- }
- list user {
- key "name";
-
- description "List of users to be added through cloud-config";
- leaf name {
- description "Name of the user ";
- type string;
- }
-
- leaf user-info {
- description "The user name's real name";
- type string;
- }
-
- list ssh-authorized-key {
- key "key-pair-ref";
-
- description "Used to configure the list of public keys to be injected as part
- of ns instantiation";
-
- leaf key-pair-ref {
- description "A reference to the key pair entry in the global key pair table";
- type leafref {
- path "../../../../../key-pair/name";
- }
- }
- }
- }
- uses manotypes:placement-group-input;
- }
- uses cloud-config;
++ uses cloud-config;
}
grouping vnffgr {
configuring: At least one of the VNFs in this instance is in configuring state
configured: All the VNFs in this NS instance are configured or config-not-needed state
";
- type config-states;
- }
-
- list service-primitive {
- description
- "Network service level service primitives.";
+ type config-states;
+ }
- key "name";
+ list service-primitive {
+ description
+ "Network service level service primitives.";
- leaf name {
- description
- "Name of the service primitive.";
- type string;
- }
+ key "name";
- list parameter {
- description
- "List of parameters for the service primitive.";
+ leaf name {
+ description
+ "Name of the service primitive.";
+ type string;
+ }
- key "name";
- uses manotypes:primitive-parameter;
- }
+ list parameter {
+ description
+ "List of parameters for the service primitive.";
- uses manotypes:ui-primitive-group;
+ key "name";
+ uses manotypes:primitive-parameter;
+ }
- list vnf-primitive-group {
- description
- "List of service primitives grouped by VNF.";
+ uses manotypes:ui-primitive-group;
- key "member-vnf-index-ref";
- leaf member-vnf-index-ref {
+ list vnf-primitive-group {
description
- "List of service primitives grouped by VNF.";
+ "Reference to member-vnf within constituent-vnfds";
- type string;
- }
- leaf vnfd-id-ref {
- description
- "A reference to a vnfd. This is a
- leafref to path:
- ../../../../nsd:constituent-vnfd
- + [nsd:id = current()/../nsd:id-ref]
- + /nsd:vnfd-id-ref
- NOTE: An issue with confd is preventing the
- use of xpath. Seems to be an issue with leafref
- to leafref, whose target is in a different module.
- Once that is resolved this will switched to use
- leafref";
-
- type string;
- }
-
- leaf vnfd-name {
- description
- "Name of the VNFD";
- type string;
- }
+ key "member-vnf-index-ref";
+ leaf member-vnf-index-ref {
+ description
+ "Reference to member-vnf within constituent-vnfds";
+ type string;
+ }
- list primitive {
- key "index";
+ leaf vnfd-id-ref {
+ description
+ "A reference to a vnfd. This is a
+ leafref to path:
+ ../../../../nsd:constituent-vnfd
+ + [nsd:id = current()/../nsd:id-ref]
+ + /nsd:vnfd-id-ref
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
- leaf index {
- description "Index of this primitive";
- type uint32;
- }
+ type string;
+ }
- leaf name {
- description "Name of the primitive in the VNF primitive ";
+ leaf vnfd-name {
+ description
+ "Name of the VNFD";
type string;
- }
- }
- }
+ }
- leaf user-defined-script {
- description
- "A user defined script.";
- type string;
- }
- }
+ list primitive {
+ key "index";
- list initial-config-primitive {
- rwpb:msg-new NsrInitialConfigPrimitive;
- description
- "Initial set of configuration primitives for NSD.";
- key "seq";
- leaf seq {
- description
- "Sequence number for the configuration primitive.";
- type uint64;
- }
+ leaf index {
+ description "Index of this primitive";
+ type uint32;
+ }
- leaf name {
- description
- "Name of the configuration primitive.";
- type string;
- mandatory "true";
+ leaf name {
+ description "Name of the primitive in the VNF primitive ";
+ type string;
+ }
+ }
+ }
+
+ leaf user-defined-script {
+ description
- "A user defined script.";
++ "A user defined script.";
+ type string;
+ }
}
- leaf user-defined-script {
+ list initial-config-primitive {
+ rwpb:msg-new NsrInitialConfigPrimitive;
description
- "A user defined script.";
- type string;
- }
+ "Initial set of configuration primitives for NSD.";
+ key "seq";
+ leaf seq {
+ description
+ "Sequence number for the configuration primitive.";
+ type uint64;
+ }
- list parameter {
- key "name";
leaf name {
+ description
+ "Name of the configuration primitive.";
type string;
+ mandatory "true";
}
- leaf value {
+ leaf user-defined-script {
+ description
+ "A user defined script.";
type string;
}
+
+ list parameter {
+ key "name";
+ leaf name {
+ type string;
+ }
+
+ leaf value {
+ type string;
+ }
+ }
}
- }
- list monitoring-param {
- description
- "List of NS level params.";
- key "id";
+ list monitoring-param {
+ description
+ "List of NS level params.";
+ key "id";
- uses manotypes:monitoring-param-value;
- uses manotypes:monitoring-param-ui-data;
- uses manotypes:monitoring-param-aggregation;
+ uses manotypes:monitoring-param-value;
+ uses manotypes:monitoring-param-ui-data;
+ uses manotypes:monitoring-param-aggregation;
- leaf id {
- type string;
- }
+ leaf id {
+ type string;
+ }
- leaf name {
- type string;
- }
+ leaf name {
+ type string;
+ }
- leaf nsd-mon-param-ref {
- description "Reference to the NSD monitoring param descriptor
+ leaf nsd-mon-param-ref {
+ description "Reference to the NSD monitoring param descriptor
that produced this result";
- type leafref {
- path "/nsd:nsd-catalog/nsd:nsd[nsd:id = current()/" +
- "../../nsr:nsd-ref]/nsd:monitoring-param/nsd:id";
+ // TODO: Fix leafref
+ type leafref {
+ path "../../../../project-nsd:nsd-catalog/project-nsd:nsd" +
+ "[project-nsd:id = current()/../../nsd-ref]" +
+ "/project-nsd:monitoring-param/project-nsd:id";
+ }
}
- }
- list vnfr-mon-param-ref {
- description "A list of VNFR monitoring params associated with this monp";
- key "vnfr-id-ref vnfr-mon-param-ref";
+ list vnfr-mon-param-ref {
+ description "A list of VNFR monitoring params associated with this monp";
+ key "vnfr-id-ref vnfr-mon-param-ref";
- leaf vnfr-id-ref {
- description
- "A reference to a vnfr. This is a
+ leaf vnfr-id-ref {
+ description
+ "A reference to a vnfr. This is a
leafref to path:
/vnfr:vnfr-catalog/vnfr:vnfr/vnfr:id";
}
}
-
+ rpc start-network-service {
+ description "Start the network service";
+ input {
+ leaf name {
+ mandatory true;
+ description "Name of the Network Service";
+ type string;
+ }
+
+ uses rpc-common;
+
+ uses ns-instance-config-params-common;
+
+ list vnfd-placement-group-maps {
+ description
+ "Mapping from mano-placement groups construct from VNFD to cloud
+ platform placement group construct";
+
+ key "placement-group-ref vnfd-id-ref";
+
+ leaf vnfd-id-ref {
+ description
+ "A reference to a vnfd. This is a
+ leafref to path:
+ ../../../../project-nsd:constituent-vnfd
+ + [id = current()/../project-nsd:id-ref]
+ + /project-nsd:vnfd-id-ref
+ NOTE: An issue with confd is preventing the
+ use of xpath. Seems to be an issue with leafref
+ to leafref, whose target is in a different module.
+ Once that is resovled this will switched to use
+ leafref";
+ type yang:uuid;
+ }
+
+ leaf placement-group-ref {
+ description
+ "A reference to VNFD placement group";
+ type leafref {
+ path "/rw-project:project[rw-project:name=current()/" +
+ "../../project-name]/project-vnfd:vnfd-catalog/project-vnfd:vnfd[project-vnfd:id = " +
+ "current()/../vnfd-id-ref]/project-vnfd:placement-groups/project-vnfd:name";
+ }
+ }
+
+ uses manotypes:placement-group-input;
+
+ list ssh-authorized-key {
+ key "key-pair-ref";
+
+ description "List of authorized ssh keys as part of cloud-config";
+
+ leaf key-pair-ref {
+ description "A reference to the key pair entry in the global key pair table";
+ type leafref {
+ path "/rw-project:project[rw-project:name=current()/../../../" +
+ "project-name]/key-pair/name";
+ }
+ }
+ }
+
+ list user {
+ key "name";
+
+ description "List of users to be added through cloud-config";
+ leaf name {
+ description "Name of the user ";
+ type string;
+ }
+ leaf user-info {
+ description "The user name's real name";
+ type string;
+ }
+ list ssh-authorized-key {
+ key "key-pair-ref";
+
+ description "Used to configure the list of public keys to be injected as part
+ of ns instantiation";
+
+ leaf key-pair-ref {
+ description "A reference to the key pair entry in the global key pair table";
+ type leafref {
+ path "/rw-project:project[rw-project:name=current()/" +
+ "../../../../project-name]/key-pair/name";
+ }
+ }
+ }
+ }
+ }
+ }
+
+ output {
+ leaf nsr-id {
+ description "Automatically generated parameter";
+ type yang:uuid;
+ }
+ }
+ }
}
"Derived from earlier versions of base YANG files";
}
- container pnfd-catalog {
+ augment "/rw-project:project" {
+ container pnfd-catalog {
- list pnfd {
- key "id";
+ list pnfd {
+ key "id";
- leaf id {
- description "Identifier for the PNFD.";
- type yang:uuid;
- }
+ leaf id {
+ description "Identifier for the PNFD.";
+ type yang:uuid;
+ }
- leaf name {
- description "PNFD name.";
- type string;
- }
+ leaf name {
+ description "PNFD name.";
+ type string;
+ }
- leaf short-name {
- description "Short name to appear as label in the UI";
- type string;
- }
+ leaf short-name {
- description "PNFD short name.";
++ description "Short name to appear as label in the UI";
+ type string;
+ }
- leaf vendor {
- description "Vendor of the PNFD.";
- type string;
- }
+ leaf vendor {
+ description "Vendor of the PNFD.";
+ type string;
+ }
- leaf description {
- description "Description of the PNFD.";
- type string;
- }
+ leaf description {
+ description "Description of the PNFD.";
+ type string;
+ }
- leaf version {
- description "Version of the PNFD";
- type string;
- }
+ leaf version {
+ description "Version of the PNFD";
+ type string;
+ }
- list connection-point {
- description
+ list connection-point {
+ description
"List for external connection points. Each PNF has one or more external
connection points.";
- key "id";
- leaf id {
- description
+ key "id";
+ leaf id {
+ description
"Identifier for the external connection points";
- type uint64;
- }
+ type uint64;
+ }
- leaf cp-type {
- description
+ leaf cp-type {
+ description
"Type of the connection point.";
- type manotypes:connection-point-type;
+ type manotypes:connection-point-type;
+ }
}
}
}
"Derived from earlier versions of base YANG files";
}
- container vlr-catalog {
- config false;
+ augment "/rw-project:project" {
+ container vlr-catalog {
+ config false;
- list vlr {
- key "id";
- unique "name";
+ list vlr {
+ key "id";
+ unique "name";
- leaf id {
- description "Identifier for the VLR.";
- type yang:uuid;
- }
+ leaf id {
+ description "Identifier for the VLR.";
+ type yang:uuid;
+ }
- leaf name {
- description "VLR name.";
- type string;
- }
+ leaf name {
+ description "VLR name.";
+ type string;
+ }
- leaf nsr-id-ref {
- description
+ leaf nsr-id-ref {
+ description
"NS instance identifier.
- This is a leafref /nsr:ns-instance-config/nsr:nsr/nsr:id";
- type yang:uuid;
- }
+ This is a leafref /rw-project:project/nsr:ns-instance-config/nsr:nsr/nsr:id";
+ type yang:uuid;
+ }
- leaf vld-ref {
- description
- "Reference to VLD
- /nsr:ns-instance-config/nsr:nsr[nsr:id=../nsr-id-ref]/nsd/vld:vld/vld:id";
- type string;
- }
+ leaf vld-ref {
+ description
+ "Reference to VLD
+ /rw-project:project/nsr:ns-instance-config/nsr:nsr[nsr:id=../nsr-id-ref]
+ /nsd/vld:vld/vld:id";
+ type string;
+ }
- leaf res-id {
- description "Identifier for resmgr id mapping";
- type yang:uuid;
- }
+ leaf res-id {
+ description "Identifier for resmgr id mapping";
+ type yang:uuid;
+ }
- leaf short-name {
- description "Short name to appear as label in the UI";
- type string;
- }
+ leaf short-name {
- description "Short name for VLR for UI";
++ description "Short name to appear as label in the UI";
+ type string;
+ }
- leaf vendor {
- description "Provider of the VLR.";
- type string;
- }
+ leaf vendor {
+ description "Provider of the VLR.";
+ type string;
+ }
- leaf description {
- description "Description of the VLR.";
- type string;
- }
+ leaf description {
+ description "Description of the VLR.";
+ type string;
+ }
- leaf version {
- description "Version of the VLR";
- type string;
- }
+ leaf version {
+ description "Version of the VLR";
+ type string;
+ }
- leaf type {
- type manotypes:virtual-link-type;
- }
+ leaf type {
+ type manotypes:virtual-link-type;
+ }
- leaf root-bandwidth {
- description
+ leaf root-bandwidth {
+ description
"For ELAN this is the aggregate bandwidth.";
- type uint64;
- }
+ type uint64;
+ }
- leaf leaf-bandwidth {
- description
+ leaf leaf-bandwidth {
+ description
"For ELAN this is the bandwidth of branches.";
- type uint64;
- }
+ type uint64;
+ }
- leaf create-time {
- description
- "Creation timestamp of this Virtual Link.
+ leaf create-time {
+ description
+ "Creation timestamp of this Virtual Link.
The timestamp is expressed as seconds
since unix epoch - 1970-01-01T00:00:00Z";
rw-nsm
rw-nsr
rw-pb-ext
+rw-project
+rw-project-mano
+rw-project-nsd
+rw-project-vnfd
rw-resource-mgr
rw-restportforward
- rwsdn
+ rwsdnal
rw-sdn
rwshell-mgmt
rw-sorch
for group in self.nsd_msg.placement_groups:
for member_vnfd in group.member_vnfd:
if (member_vnfd.vnfd_id_ref == vnfd_msg.id) and \
- (member_vnfd.member_vnf_index_ref == const_vnfd.member_vnf_index):
+ (member_vnfd.member_vnf_index_ref == str(const_vnfd.member_vnf_index)):
group_info = self.resolve_placement_group_cloud_construct(group)
if group_info is None:
- self._log.error("Could not resolve cloud-construct for placement group: %s", group.name)
+ self._log.info("Could not resolve cloud-construct for placement group: %s", group.name)
### raise PlacementGroupError("Could not resolve cloud-construct for placement group: {}".format(group.name))
else:
self._log.info("Successfully resolved cloud construct for placement group: %s for VNF: %s (Member Index: %s)",
class SchemaRpcHandler(mano_dts.AbstractRpcHandler):
"""RPC handler to generate the schema for the packages.
"""
-- def __init__(self, log, dts, loop, proxy):
++ def __init__(self, log, dts, loop, project, proxy):
"""
Args:
proxy: Any impl of .proxy.AbstractPackageManagerProxy
"""
-- super().__init__(log, dts, loop)
++ super().__init__(log, dts, loop, project)
self.proxy = proxy
@property
return rpc_op
- def __init__(self, log, dts, loop, proxy, publisher):
+ class PackageCopyOperationsRpcHandler(mano_dts.AbstractRpcHandler):
- super().__init__(log, dts, loop)
++ def __init__(self, log, dts, loop, project, proxy, publisher):
+ """
+ Args:
+ proxy: Any impl of .proxy.AbstractPackageManagerProxy
+ publisher: CopyStatusPublisher object
+ """
++ super().__init__(log, dts, loop, project)
+ self.proxy = proxy
+ self.publisher = publisher
+
+ @property
+ def xpath(self):
+ return "/rw-pkg-mgmt:package-copy"
+
+ @asyncio.coroutine
+ def callback(self, ks_path, msg):
+ import uuid
+ copier = pkg_downloader.PackageFileCopier.from_rpc_input(msg, proxy=self.proxy, log=self.log)
+
+ transaction_id, dest_package_id = yield from self.publisher.register_copier(copier)
+ rpc_op = RPC_PACKAGE_COPY_ENDPOINT.from_dict({
+ "transaction_id":transaction_id,
+ "package_id":dest_package_id,
+ "package_type":msg.package_type})
+
+ return rpc_op
class PackageDeleteOperationsRpcHandler(mano_dts.AbstractRpcHandler):
def __init__(self, log, dts, loop, proxy):
from . import publisher as pkg_publisher
from . import subscriber
-
+class PackageManagerProject(ManoProject):
+
+ def __init__(self, name, tasklet, **kw):
+ super(PackageManagerProject, self).__init__(tasklet.log, name)
+ self.update(tasklet)
++ proxy = kw["proxy"]
+
+ args = [self.log, self.dts, self.loop, self]
+ self.job_handler = pkg_publisher.DownloadStatusPublisher(*args)
++ self.copy_publisher = pkg_publisher.CopyStatusPublisher(*args + [self.tasklet.tasklet_info])
++
+ # create catalog subscribers
+ self.vnfd_catalog_sub = subscriber.VnfdStatusSubscriber(*args)
+ self.nsd_catalog_sub = subscriber.NsdStatusSubscriber(*args)
++
++ args.append(proxy)
++ self.copy_rpc = rpc.PackageCopyOperationsRpcHandler(*(args + [self.copy_publisher]))
+
+ @asyncio.coroutine
+ def register (self):
+ yield from self.vnfd_catalog_sub.register()
+ yield from self.nsd_catalog_sub.register()
++ yield from self.copy_rpc.register()
++ yield from self.copy_publisher.register()
+ yield from self.job_handler.register()
+
+ def deregister (self):
+ yield from self.job_handler.deregister()
++ yield from self.copy_rpc.deregister()
++ yield from self.copy_publisher.deregister()
+ yield from self.vnfd_catalog_sub.deregister()
+ yield from self.nsd_catalog_sub.deregister()
+
+
class PackageManagerTasklet(rift.tasklets.Tasklet):
def __init__(self, *args, **kwargs):
try:
self.loop,
self.on_dts_state_change
)
-
+
- proxy = filesystem.FileSystemProxy(self.loop, self.log)
+ proxy = filesystem.FileSystemProxy(self.loop, self.log)
+ args = [self.log, self.dts, self.loop]
- args = [self.log, self.dts, self.loop]
- args.append(proxy)
- self.endpoint_rpc = rpc.EndpointDiscoveryRpcHandler(*args)
- self.schema_rpc = rpc.SchemaRpcHandler(*args)
- self.delete_rpc = rpc.PackageDeleteOperationsRpcHandler(*args)
- # create catalog publishers
- self.job_handler = pkg_publisher.DownloadStatusPublisher(*args)
- self.copy_publisher = pkg_publisher.CopyStatusPublisher(*args +[self.tasklet_info])
-
- # create catalog subscribers
- self.vnfd_catalog_sub = subscriber.VnfdStatusSubscriber(*args)
- self.nsd_catalog_sub = subscriber.NsdStatusSubscriber(*args)
-
+ args.append(proxy)
+ self.endpoint_rpc = rpc.EndpointDiscoveryRpcHandler(*args)
+ self.schema_rpc = rpc.SchemaRpcHandler(*args)
+ self.delete_rpc = rpc.PackageDeleteOperationsRpcHandler(*args)
- self.copy_rpc = rpc.PackageCopyOperationsRpcHandler(*(args + [self.copy_publisher]))
+
- args.append(self.job_handler)
++ args.append(self)
+ self.pkg_op = rpc.PackageOperationsRpcHandler(*args)
- args.append(self)
- self.pkg_op = rpc.PackageOperationsRpcHandler(*args)
++ self.project_handler = ProjectHandler(self, PackageManagerProject,
++ proxy=proxy,)
+ except Exception as e:
- self.log.error("Exception caught rwpkgmgr start: %s", str(e))
++ self.log.exception("Exception caught rwpkgmgr start: %s", str(e))
+ else:
+ self.log.debug("rwpkgmgr started successfully!")
def stop(self):
try:
)
import rift.tasklets
+from rift.mano.utils.project import (
+ ManoProject,
+ ProjectHandler,
+)
+ import rift.mano.sdn
from rift.vlmgr import (
VlrDtsHandler,
""" Vlr Record not found"""
pass
- class SdnAccountError(Exception):
- """ Error while creating/deleting/updating SDN Account"""
- pass
- class SdnAccountNotFound(Exception):
- pass
-
- class SDNAccountDtsOperdataHandler(object):
- def __init__(self, dts, log, loop, parent):
- self._dts = dts
+ class SDNAccountHandlers(object):
- def __init__(self, dts, log, log_hdl, acctstore, loop):
++ def __init__(self, dts, log, log_hdl, acctstore, loop, project):
self._log = log
+ self._log_hdl = log_hdl
+ self._dts = dts
self._loop = loop
- self._parent = parent
- self._project = self._parent._project
- self._regh = None
- self._rpch = None
-
- def _register_show_status(self):
- def get_xpath(sdn_name=None):
- return self._project.add_project("D,/rw-sdn:sdn/rw-sdn:account{}" \
- "/rw-sdn:connection-status".format(
- "[name='%s']" % sdn_name if sdn_name is not None else ''
- ))
-
- @asyncio.coroutine
- def on_prepare(xact_info, action, ks_path, msg):
- path_entry = RwSdnYang.SDNAccountConfig.schema().keyspec_to_entry(ks_path)
- sdn_account_name = path_entry.key00.name
- self._log.debug("Got show sdn connection status request: %s", ks_path.create_string())
-
- try:
- saved_accounts = self._parent._acctmgr.get_saved_sdn_accounts(sdn_account_name)
- for account in saved_accounts:
- sdn_acct = RwSdnYang.SDNAccountConfig()
- sdn_acct.from_dict(account.as_dict())
-
- self._log.debug("Responding to sdn connection status request: %s", sdn_acct.connection_status)
- xact_info.respond_xpath(
- rwdts.XactRspCode.MORE,
- xpath=get_xpath(account.name),
- msg=sdn_acct.connection_status,
- )
- except KeyError as e:
- self._log.warning(str(e))
- xact_info.respond_xpath(rwdts.XactRspCode.NA)
- return
-
- xact_info.respond_xpath(rwdts.XactRspCode.ACK)
+ self._acctstore = acctstore
++ self._project = project
+
+ self._log.debug("Creating SDN account config handler")
+ self.sdn_cfg_handler = rift.mano.sdn.SDNAccountConfigSubscriber(
- self._dts, self._log, self._log_hdl,
++ self._dts, self._log, project, self._log_hdl,
+ rift.mano.sdn.SDNAccountConfigCallbacks(
+ on_add_apply=self.on_sdn_account_added,
+ on_delete_apply=self.on_sdn_account_deleted,
+ ),
+ self._acctstore
- self._regh = yield from self._dts.register(
- xpath=get_xpath(),
- handler=rift.tasklets.DTS.RegistrationHandler(
- on_prepare=on_prepare),
- flags=rwdts.Flag.PUBLISHER,
)
-
- def _register_validate_rpc(self):
- def get_xpath():
- return "/rw-sdn:update-sdn-status"
-
- @asyncio.coroutine
- def on_prepare(xact_info, action, ks_path, msg):
-
- if not self._project.rpc_check(msg, xact_info=xact_info):
- return
-
- if not msg.has_field("sdn_account"):
- raise SdnAccountNotFound("SDN account name not provided")
-
- sdn_account_name = msg.sdn_account
- account = self._parent._acctmgr.get_sdn_account(sdn_account_name)
- if account is None:
- self._log.warning("SDN account %s does not exist", sdn_account_name)
- xact_info.respond_xpath(rwdts.XactRspCode.NA)
- return
-
- self._parent._acctmgr.start_validate_credentials(self._loop, sdn_account_name)
-
- xact_info.respond_xpath(rwdts.XactRspCode.ACK)
-
- self._rpch = yield from self._dts.register(
- xpath=get_xpath(),
- handler=rift.tasklets.DTS.RegistrationHandler(
- on_prepare=on_prepare
- ),
- flags=rwdts.Flag.PUBLISHER,
+
+ self._log.debug("Creating SDN account opdata handler")
+ self.sdn_operdata_handler = rift.mano.sdn.SDNAccountDtsOperdataHandler(
- self._dts, self._log, self._loop,
++ self._dts, self._log, self._loop, project,
)
-
- @asyncio.coroutine
- def register(self):
- yield from self._register_show_status()
- yield from self._register_validate_rpc()
-
- def deregister(self):
- self._log.debug("De-register SDN opdata handler for project {}".
- format(self._project.name))
- if self._regh:
- self._regh.deregister()
- self._regh = None
-
- if self._rpch:
- self._rpch.deregister()
- self._rpch = None
-
-
- class SDNAccountDtsHandler(object):
- XPATH = "C,/rw-sdn:sdn/rw-sdn:account"
-
- def __init__(self, dts, log, parent):
- self._dts = dts
- self._log = log
- self._parent = parent
- self._project = parent._project
-
- self._sdn_account = {}
- self._regh = None
-
- @property
- def _xpath(self):
- return self._project.add_project(SDNAccountDtsHandler.XPATH)
-
- def _set_sdn_account(self, account):
- self._log.info("Setting sdn account: {}".format(account))
- if account.name in self._sdn_account:
- self._log.error("SDN Account with name %s already exists. Ignoring config", account.name);
- self._sdn_account[account.name] = account
- self._parent._acctmgr.set_sdn_account(account)
-
- def _del_sdn_account(self, account_name):
- self._log.info("Deleting sdn account: {}".format(account_name))
- del self._sdn_account[account_name]
-
- self._parent._acctmgr.del_sdn_account(account_name)
-
- def _update_sdn_account(self, account):
- self._log.info("Updating sdn account: {}".format(account))
- # No need to update locally saved sdn_account's updated fields, as they
- # are not used anywhere. Call the parent's update callback.
- self._parent._acctmgr.update_sdn_account(account)
-
+
+ def on_sdn_account_deleted(self, account_name):
+ self._log.debug("SDN account deleted")
+ self.sdn_operdata_handler.delete_sdn_account(account_name)
+
+ def on_sdn_account_added(self, account):
+ self._log.debug("SDN account added")
+ self.sdn_operdata_handler.add_sdn_account(account)
+
@asyncio.coroutine
def register(self):
- def apply_config(dts, acg, xact, action, _):
- self._log.debug("Got sdn account apply config (xact: %s) (action: %s)", xact, action)
- if action == rwdts.AppconfAction.INSTALL and xact.id is None:
- self._log.debug("No xact handle. Skipping apply config")
- return RwTypes.RwStatus.SUCCESS
-
- return RwTypes.RwStatus.SUCCESS
-
- @asyncio.coroutine
- def on_prepare(dts, acg, xact, xact_info, ks_path, msg, scratch):
- """ Prepare callback from DTS for SDN Account config """
-
- self._log.info("SDN Cloud account config received: %s", msg)
-
- fref = ProtobufC.FieldReference.alloc()
- fref.goto_whole_message(msg.to_pbcm())
-
- if fref.is_field_deleted():
- # Delete the sdn account record
- self._del_sdn_account(msg.name)
- else:
- # If the account already exists, then this is an update.
- if msg.name in self._sdn_account:
- self._log.debug("SDN account already exists. Invoking on_prepare update request")
- if msg.has_field("account_type"):
- errmsg = "Cannot update SDN account's account-type."
- self._log.error(errmsg)
- xact_info.send_error_xpath(RwTypes.RwStatus.FAILURE,
- self._xpath,
- errmsg)
- raise SdnAccountError(errmsg)
-
- # Update the sdn account record
- self._update_sdn_account(msg)
- else:
- self._log.debug("SDN account does not already exist. Invoking on_prepare add request")
- if not msg.has_field('account_type'):
- errmsg = "New SDN account must contain account-type field."
- self._log.error(errmsg)
- xact_info.send_error_xpath(RwTypes.RwStatus.FAILURE,
- self._xpath,
- errmsg)
- raise SdnAccountError(errmsg)
-
- # Set the sdn account record
- self._set_sdn_account(msg)
-
- xact_info.respond_xpath(rwdts.XactRspCode.ACK)
-
-
- self._log.debug("Registering for Sdn Account config using xpath: {}".
- format(self._xpath))
-
- acg_handler = rift.tasklets.AppConfGroup.Handler(
- on_apply=apply_config,
- )
-
- with self._dts.appconf_group_create(acg_handler) as acg:
- self._regh = acg.register(
- xpath=self._xpath,
- flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY,
- on_prepare=on_prepare
- )
+ self.sdn_cfg_handler.register()
+ yield from self.sdn_operdata_handler.register()
- self._log.debug("De-register VLR handler for project {}".
- format(self._project.name))
- if self._regh:
- self._regh.deregister()
- self._regh = None
+ def deregister(self):
++ self.sdn_cfg_handler.deregister()
++ self.sdn_operdata_handler.deregister()
+
class VnsManager(object):
""" The Virtual Network Service Manager """
self._log = log
self._log_hdl = log_hdl
self._loop = loop
-
+ self._project = project
+ self._acctstore = {}
self._vlr_handler = VlrDtsHandler(dts, log, loop, self)
self._vld_handler = VldDtsHandler(dts, log, loop, self)
- self._sdn_handler = SDNAccountDtsHandler(dts,log,self)
- self._sdn_opdata_handler = SDNAccountDtsOperdataHandler(dts,log, loop, self)
- self._acctmgr = SdnAccountMgr(self._log, self._log_hdl, self._loop, self._project)
- self._sdn_handlers = SDNAccountHandlers(dts, log, log_hdl, self._acctstore, loop)
++ self._sdn_handlers = SDNAccountHandlers(dts, log, log_hdl, self._acctstore, loop, project)
self._nwtopdata_store = NwtopDataStore(log)
- self._nwtopdiscovery_handler = NwtopDiscoveryDtsHandler(dts, log, loop, self._project,
- self._acctmgr, self._nwtopdata_store)
- self._nwtopstatic_handler = NwtopStaticDtsHandler(dts, log, loop, self._project,
- self._acctmgr, self._nwtopdata_store)
- self._nwtopdiscovery_handler = NwtopDiscoveryDtsHandler(dts, log, loop, self._acctstore, self._nwtopdata_store)
- self._nwtopstatic_handler = NwtopStaticDtsHandler(dts, log, loop, self._acctstore, self._nwtopdata_store)
++ self._nwtopdiscovery_handler = NwtopDiscoveryDtsHandler(dts, log, loop, project,
++ self._acctstore, self._nwtopdata_store)
++ self._nwtopstatic_handler = NwtopStaticDtsHandler(dts, log, loop, project,
++ self._acctstore, self._nwtopdata_store)
self._vlrs = {}
@asyncio.coroutine
yield from self.register_vlr_handler()
yield from self.register_vld_handler()
yield from self.register_nwtopstatic_handler()
- # Not used for now
yield from self.register_nwtopdiscovery_handler()
- self._sdn_opdata_handler.deregister()
- self._sdn_handler.deregister()
+ def deregister(self):
+ self._nwtopdiscovery_handler.deregister()
+ self._nwtopstatic_handler.deregister()
+ self._vld_handler.deregister()
+ self._vlr_handler.deregister()
++ self._sdn_handlers.deregister()
+
def create_vlr(self, msg):
""" Create VLR """
if msg.id in self._vlrs:
""" Handles DTS interactions for the Discovered Topology registration """
DISC_XPATH = "D,/nd:network"
- def __init__(self, dts, log, loop, project, acctmgr, nwdatastore):
- def __init__(self, dts, log, loop, acctstore, nwdatastore):
++ def __init__(self, dts, log, loop, project, acctstore, nwdatastore):
self._dts = dts
self._log = log
self._loop = loop
- self._acctmgr = acctmgr
+ self._project = project
+ self._acctstore = acctstore
self._nwdatastore = nwdatastore
self._regh = None
""" Handles DTS interactions for the Static Topology registration """
STATIC_XPATH = "C,/nd:network"
- def __init__(self, dts, log, loop, project, acctmgr, nwdatastore):
- def __init__(self, dts, log, loop, acctstore, nwdatastore):
++ def __init__(self, dts, log, loop, project, acctstore, nwdatastore):
self._dts = dts
self._log = log
self._loop = loop
- self._acctmgr = acctmgr
+ self._project = project
+ self._acctstore = acctstore
self._regh = None
self.pending = {}
VALA_FILES ${VALA_FILES}
VALA_PACKAGES
rw_types-1.0 rw_yang-1.0 rw_keyspec-1.0 rw_yang_pb-1.0 rw_schema_proto-1.0
- rw_log_yang-1.0 rw_base_yang-1.0 rwcal_yang-1.0 rwsdn_yang-1.0 rw_manifest_yang-1.0 protobuf_c-1.0 ietf_netconf_yang-1.0
+ rw_log_yang-1.0 rw_base_yang-1.0 rwcal_yang-1.0 rwsdnal_yang-1.0 rw_manifest_yang-1.0 protobuf_c-1.0 ietf_netconf_yang-1.0
ietf_network_yang-1.0 ietf_network_topology_yang-1.0
ietf_l2_topology_yang-1.0 rw_topology_yang-1.0
- rw_log-1.0
+ rw_log-1.0 rw_project_yang-1.0
VAPI_DIRS
${RIFT_SUBMODULE_BINARY_ROOT}/models/plugins/yang
${RIFT_SUBMODULE_BINARY_ROOT}/rwcal/plugins/yang
GENERATE_VAPI_FILE ${VALA_LONG_NAME}.vapi
GENERATE_GIR_FILE ${VALA_TYPELIB_PREFIX}.gir
GENERATE_TYPELIB_FILE ${VALA_TYPELIB_PREFIX}.typelib
- DEPENDS rwcal_yang rwsdn_yang mano_yang rwlog_gi rwschema_yang rwproject_yang
- DEPENDS rwcal_yang rwsdnal_yang mano_yang rwlog_gi rwschema_yang
++ DEPENDS rwcal_yang rwsdnal_yang mano_yang rwlog_gi rwschema_yang rwproject_yang
)
rift_install_vala_artifacts(
--- /dev/null
- uses connection-status;
+
+ /*
+ *
+ * Copyright 2016-2017 RIFT.IO Inc
+ *
+ * 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.
+ *
+ *
+ */
+
+ module rwsdnal
+ {
+ namespace "http://riftio.com/ns/riftware-1.0/rwsdnal";
+ prefix "rwsdnal";
+
+ import rw-base {
+ prefix rwbase;
+ }
+
+ import rw-pb-ext {
+ prefix "rwpb";
+ }
+
+ import rw-yang-types {
+ prefix "rwt";
+ }
+
+ import rw-log {
+ prefix "rwlog";
+ }
+
+ import mano-types {
+ prefix "manotypes";
+ }
+
+ import ietf-inet-types {
+ prefix "inet";
+ }
+
+ import ietf-yang-types {
+ prefix "yang";
+ }
+
++ import rw-project {
++ prefix "rw-project";
++ }
++
++ revision 2017-02-08 {
++ description
++ "Update model to support projects.";
++ }
+
+ revision 2014-12-30 {
+ description
+ "Initial revision.";
+ reference
+ "RIFT RWSDN cloud data";
+ }
+
+ typedef sdn-connection-status-enum {
+ description "Connection status for the sdn account";
+ type enumeration {
+ enum unknown;
+ enum validating;
+ enum success;
+ enum failure;
+ }
+ }
+
+ grouping connection-status {
+ container connection-status {
+ config false;
+ rwpb:msg-new SdnConnectionStatus;
+ leaf status {
+ type sdn-connection-status-enum;
+ }
+ leaf details {
+ type string;
+ }
+ }
+ }
+
- container sdn-accounts {
- list sdn-account-list {
- rwpb:msg-new SDNAccount;
- key "name";
++ // uses connection-status;
+
+ typedef sdn-account-type {
+ description "SDN account type";
+ type enumeration {
+ enum odl;
+ enum mock;
+ enum sdnsim;
+ enum openstack;
+ }
+ }
+
+ grouping sdn-provider-auth {
+ leaf account-type {
+ type sdn-account-type;
+ }
+
+ choice provider-specific-info {
+ container odl {
+ leaf username {
+ type string {
+ length "1..255";
+ }
+ }
+
+ leaf password {
+ type string {
+ length "1..32";
+ }
+ }
+
+ leaf url {
+ type string {
+ length "1..255";
+ }
+ }
+ leaf plugin-name {
+ type string;
+ default "rwsdn_odl";
+ }
+ }
+ container mock {
+ leaf username {
+ type string;
+ }
+ leaf plugin-name {
+ type string;
+ default "rwsdn_mock";
+ }
+ }
+
+ container sdnsim {
+ leaf username {
+ type string;
+ }
+ leaf topology-source {
+ type string;
+ }
+ leaf plugin-name {
+ type string;
+ default "rwsdn_sim";
+ }
+ }
+
+ container openstack {
+ leaf key {
+ type string;
+ mandatory true;
+ }
+
+ leaf secret {
+ type string;
+ mandatory true;
+ }
+
+ leaf auth_url {
+ type string;
+ mandatory true;
+ }
+
+ leaf tenant {
+ type string;
+ mandatory true;
+ }
+
+ leaf admin {
+ type boolean;
+ default false;
+ }
+
+ leaf user-domain {
+ type string;
+ default "Default";
+ description "Domain of the OpenStack user";
+ }
+
+ leaf project-domain {
+ type string;
+ default "Default";
+ description "Domain of the OpenStack project";
+ }
+
+ leaf region {
+ type string;
+ default "RegionOne";
+ }
+
+ leaf plugin-name {
+ type string;
+ default "rwsdn_openstack";
+ }
+
+ leaf cert-validate {
+ type boolean;
+ default false;
+ description "Certificate validatation policy in case of SSL/TLS connection";
+ }
+ }
+
+ }
+ }
+
- leaf name {
- type string;
- }
++ augment "/rw-project:project" {
++ container sdn-accounts {
++ list sdn-account-list {
++ rwpb:msg-new SDNAccount;
++ key "name";
+
- uses sdn-provider-auth;
- uses connection-status;
++ leaf name {
++ type string;
++ }
+
- container vnffgs {
- list vnffg-chain {
- key "name";
- rwpb:msg-new VNFFGChain;
-
- leaf name {
- type string;
- }
++ uses sdn-provider-auth;
++ uses connection-status;
++ }
+ }
+ }
+
- list vnf-chain-path {
- key "order";
- leaf order {
- type uint32;
- description " Order of the VNF in VNFFG chain";
- }
- leaf service-function-type {
- type string;
- }
- leaf nsh-aware {
- type boolean;
- }
- leaf transport-type {
++ augment "/rw-project:project" {
++ container vnffgs {
++ list vnffg-chain {
++ key "name";
++ rwpb:msg-new VNFFGChain;
+
- list vnfr-ids {
- key "vnfr-id";
- leaf vnfr-id {
- type yang:uuid;
++ leaf name {
+ type string;
+ }
- leaf vnfr-name {
++
++ list vnf-chain-path {
++ key "order";
++ leaf order {
++ type uint32;
++ description " Order of the VNF in VNFFG chain";
+ }
- leaf mgmt-address {
- type inet:ip-address;
++ leaf service-function-type {
+ type string;
+ }
- leaf mgmt-port {
- type inet:port-number;
++ leaf nsh-aware {
++ type boolean;
+ }
- list vdu-list {
- key "vm-id port-id";
- leaf port-id {
- rwpb:field-inline "true";
- rwpb:field-string-max 64;
- type string;
- }
- leaf vm-id {
- rwpb:field-inline "true";
- rwpb:field-string-max 64;
- type string;
++ leaf transport-type {
++ type string;
+ }
- leaf name {
++ list vnfr-ids {
++ key "vnfr-id";
++ leaf vnfr-id {
++ type yang:uuid;
+ }
- leaf address {
++ leaf vnfr-name {
+ type string;
+ }
- leaf port {
++ leaf mgmt-address {
+ type inet:ip-address;
+ }
- leaf sff-name {
- description "SFF name useful for non OVS based SFF";
- type string;
- }
- }
- }
- list sff {
- rwpb:msg-new VNFFGSff;
- key "name";
- leaf name {
- type string;
- }
- leaf function-type {
- type string;
- }
- leaf mgmt-address {
- type inet:ip-address;
- }
- leaf mgmt-port {
- type inet:port-number;
++ leaf mgmt-port {
+ type inet:port-number;
+ }
++ list vdu-list {
++ key "vm-id port-id";
++ leaf port-id {
++ rwpb:field-inline "true";
++ rwpb:field-string-max 64;
++ type string;
++ }
++ leaf vm-id {
++ rwpb:field-inline "true";
++ rwpb:field-string-max 64;
++ type string;
++ }
++ leaf name {
++ type string;
++ }
++ leaf address {
++ type inet:ip-address;
++ }
++ leaf port {
++ type inet:port-number;
++ }
++ }
++ leaf sff-name {
++ description "SFF name useful for non OVS based SFF";
++ type string;
++ }
+ }
- list dp-endpoints {
+ }
- type string;
- }
- leaf address {
++ list sff {
++ rwpb:msg-new VNFFGSff;
+ key "name";
+ leaf name {
- leaf port {
++ type string;
++ }
++ leaf function-type {
++ type string;
++ }
++ leaf mgmt-address {
+ type inet:ip-address;
+ }
- }
- list vnfr-list {
- key "vnfr-name";
- leaf vnfr-name {
- type string;
++ leaf mgmt-port {
+ type inet:port-number;
+ }
- }
- leaf classifier-name {
- type string;
++ list dp-endpoints {
++ key "name";
++ leaf name {
++ type string;
++ }
++ leaf address {
++ type inet:ip-address;
++ }
++ leaf port {
++ type inet:port-number;
++ }
++ }
++ list vnfr-list {
++ key "vnfr-name";
++ leaf vnfr-name {
++ type string;
++ }
+ }
+ }
- container vnffg-rendered-paths {
- rwpb:msg-new VNFFGRenderedPaths;
- list vnffg-rendered-path {
- key "name";
- rwpb:msg-new VNFFGRenderedPath;
- config false;
- leaf name {
- type string;
- }
- leaf path-id {
- description
- "Unique Identifier for the service path";
- type uint32;
- }
- list rendered-path-hop {
- key "hop-number";
- leaf hop-number {
- type uint8;
- }
- leaf service-index {
- description
- "Location within the service path";
- type uint8;
- }
- leaf vnfr-name {
++ leaf classifier-name {
++ type string;
++ }
+ }
+ }
+ }
+
- container service-function-forwarder {
- leaf name {
++ augment "/rw-project:project" {
++ container vnffg-rendered-paths {
++ rwpb:msg-new VNFFGRenderedPaths;
++ list vnffg-rendered-path {
++ key "name";
++ rwpb:msg-new VNFFGRenderedPath;
++ config false;
++ leaf name {
+ type string;
+ }
- "Service Function Forwarder name";
++ leaf path-id {
++ description
++ "Unique Identifier for the service path";
++ type uint32;
++ }
++ list rendered-path-hop {
++ key "hop-number";
++ leaf hop-number {
++ type uint8;
++ }
++ leaf service-index {
+ description
- leaf ip-address {
- description
++ "Location within the service path";
++ type uint8;
++ }
++ leaf vnfr-name {
+ type string;
+ }
- type inet:ip-address;
- }
- leaf port {
- description
++ container service-function-forwarder {
++ leaf name {
++ description
++ "Service Function Forwarder name";
++ type string;
++ }
++ leaf ip-address {
++ description
+ "Service Function Forwarder Data Plane IP address";
- type inet:port-number;
- }
++ type inet:ip-address;
++ }
++ leaf port {
++ description
+ "Service Function Forwarder Data Plane port";
- container vnffg-classifiers {
- list vnffg-classifier {
- key "name";
- rwpb:msg-new VNFFGClassifier;
-
- leaf name {
- type string;
- }
- leaf rsp-name {
- type string;
- }
- leaf rsp-id {
- type yang:uuid;
- }
- leaf port-id {
- rwpb:field-inline "true";
- rwpb:field-string-max 64;
- type string;
- }
- leaf vm-id {
- rwpb:field-inline "true";
- rwpb:field-string-max 64;
- type string;
- }
- leaf sff-name {
- type string;
- }
- container vnffg-metadata {
- leaf ctx1 {
++ type inet:port-number;
++ }
++ }
+ }
+ }
+ }
+ }
+
++ augment "/rw-project:project" {
++ container vnffg-classifiers {
++ list vnffg-classifier {
++ key "name";
++ rwpb:msg-new VNFFGClassifier;
+
- leaf ctx2 {
++ leaf name {
+ type string;
+ }
- leaf ctx3 {
++ leaf rsp-name {
+ type string;
+ }
- leaf ctx4 {
++ leaf rsp-id {
++ type yang:uuid;
++ }
++ leaf port-id {
++ rwpb:field-inline "true";
++ rwpb:field-string-max 64;
+ type string;
+ }
- }
- list match-attributes {
- description
- "List of match attributes.";
- key "name";
- leaf name {
++ leaf vm-id {
++ rwpb:field-inline "true";
++ rwpb:field-string-max 64;
+ type string;
+ }
- type string;
- }
++ leaf sff-name {
++ type string;
++ }
++ container vnffg-metadata {
++ leaf ctx1 {
++ type string;
++ }
++ leaf ctx2 {
++ type string;
++ }
++ leaf ctx3 {
++ type string;
++ }
++ leaf ctx4 {
++ type string;
++ }
++ }
++ list match-attributes {
+ description
++ "List of match attributes.";
++ key "name";
++ leaf name {
++ description
+ "Name for the Access list";
- leaf ip-proto {
- description
++ type string;
++ }
+
- type uint8;
- }
++ leaf ip-proto {
++ description
+ "IP Protocol.";
- leaf source-ip-address {
- description
++ type uint8;
++ }
+
- type inet:ip-prefix;
- }
++ leaf source-ip-address {
++ description
+ "Source IP address.";
- leaf destination-ip-address {
- description
++ type inet:ip-prefix;
++ }
+
- type inet:ip-prefix;
- }
++ leaf destination-ip-address {
++ description
+ "Destination IP address.";
- leaf source-port {
- description
++ type inet:ip-prefix;
++ }
+
- type inet:port-number;
- }
++ leaf source-port {
++ description
+ "Source port number.";
- leaf destination-port {
- description
++ type inet:port-number;
++ }
+
- type inet:port-number;
- }
- } //match-attributes
++ leaf destination-port {
++ description
+ "Destination port number.";
++ type inet:port-number;
++ }
++ } //match-attributes
++ }
+ }
+ }
+
+ }
+
+ /* vim: set ts=2:sw=2: */
}
}
- container download-jobs {
- rwpb:msg-new DownloadJobs;
- description "Download jobs";
- config false;
+ grouping copy-task-status {
+ leaf status {
+ description "The status of the copy task";
+ type task-status;
+ default QUEUED;
+ }
+ }
+
+ augment "/rw-project:project" {
+ container download-jobs {
+ rwpb:msg-new DownloadJobs;
+ description "Download jobs";
+ config false;
- list job {
- rwpb:msg-new DownloadJob;
- key "download-id";
+ list job {
+ rwpb:msg-new DownloadJob;
+ key "download-id";
- leaf download-id {
- description "Unique UUID";
- type string;
- }
+ leaf download-id {
+ description "Unique UUID";
+ type string;
+ }
- leaf url {
- description "URL of the download";
- type string;
- }
+ leaf url {
+ description "URL of the download";
+ type string;
+ }
- uses package-file-identifer;
- uses download-task-status;
+ uses package-file-identifer;
+ uses download-task-status;
+ }
}
- }
+
- container copy-jobs {
- rwpb:msg-new CopyJobs;
- description "Copy jobs";
- config false;
++ container copy-jobs {
++ rwpb:msg-new CopyJobs;
++ description "Copy jobs";
++ config false;
+
- list job {
- rwpb:msg-new CopyJob;
- key "transaction-id";
++ list job {
++ rwpb:msg-new CopyJob;
++ key "transaction-id";
+
- leaf transaction-id {
- description "Unique UUID";
- type string;
- }
++ leaf transaction-id {
++ description "Unique UUID";
++ type string;
++ }
+
- uses copy-task-status;
++ uses copy-task-status;
++ }
+ }
}
rpc get-package-endpoint {
}
}
+ rpc package-copy {
+ description "Copies the package specified in input and returns the copied package id";
+
+ input {
+ uses package-identifer;
+
+ leaf package-name {
+ description "Name of destination package";
+ type string;
+ }
++
++ uses manotypes:rpc-project-name;
+ }
+
+ output {
+ leaf transaction-id {
+ description "Valid ID to track the status of the task";
+ type string;
+ }
+
+ uses package-identifer;
+ }
+ }
+
rpc get-package-schema {
description "Retrieves the schema for the package type";