Khen Nursimulu | 8ffb893 | 2017-01-26 13:40:49 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # Copyright 2017 the original author or authors. |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | # |
| 17 | import structlog |
| 18 | from netconf.nc_rpc.rpc import Rpc |
| 19 | import netconf.nc_common.error as ncerror |
| 20 | from twisted.internet.defer import inlineCallbacks, returnValue |
| 21 | import dicttoxml |
| 22 | from netconf.nc_common.utils import qmap, ns |
| 23 | from netconf.constants import Constants as C |
| 24 | from netconf.grpc_client.nc_rpc_mapper import \ |
| 25 | get_nc_rpc_mapper_instance |
| 26 | |
| 27 | log = structlog.get_logger() |
| 28 | |
| 29 | |
| 30 | class VolthaRpc(Rpc): |
| 31 | def __init__(self, request, request_xml, grpc_client, session, |
| 32 | capabilities): |
| 33 | super(VolthaRpc, self).__init__(request, request_xml, grpc_client, |
| 34 | session, capabilities) |
| 35 | self.service = None |
| 36 | self.method = None |
| 37 | self.metadata = None |
| 38 | self._extract_parameters() |
| 39 | if not self.rpc_response.is_error: |
| 40 | self._validate_parameters() |
| 41 | |
| 42 | @inlineCallbacks |
| 43 | def execute(self): |
| 44 | if self.rpc_response.is_error: |
| 45 | returnValue(self.rpc_response) |
| 46 | |
| 47 | log.info('voltha-rpc-request', session=self.session.session_id, |
| 48 | request=self.request) |
| 49 | |
| 50 | # Execute the request |
Khen Nursimulu | 3676b7c | 2017-01-31 13:48:38 -0500 | [diff] [blame] | 51 | res_dict, yang_options = yield self.grpc_client.invoke_voltha_rpc( |
Khen Nursimulu | 8ffb893 | 2017-01-26 13:40:49 -0500 | [diff] [blame] | 52 | service=self.service, |
| 53 | method=self.method, |
| 54 | params=self.request['params'], |
| 55 | metadata=self.metadata) |
| 56 | |
| 57 | # convert dict to xml |
| 58 | xml = dicttoxml.dicttoxml(res_dict, attr_type=True) |
| 59 | log.info('voltha-info', res=res_dict, xml=xml) |
| 60 | |
| 61 | root_elem = self.get_root_element(xml) |
| 62 | |
| 63 | # Build the yang response |
| 64 | self.rpc_response.node = self.rpc_response.build_yang_response( |
Khen Nursimulu | 3676b7c | 2017-01-31 13:48:38 -0500 | [diff] [blame] | 65 | root_elem, self.request, yang_options=yang_options, custom_rpc=True) |
Khen Nursimulu | 8ffb893 | 2017-01-26 13:40:49 -0500 | [diff] [blame] | 66 | self.rpc_response.is_error = False |
| 67 | |
| 68 | returnValue(self.rpc_response) |
| 69 | |
| 70 | def _validate_parameters(self): |
| 71 | log.info('validate-parameters', session=self.session.session_id) |
| 72 | # For now just validate that the command is presenf |
| 73 | if self.request: |
| 74 | try: |
| 75 | if self.request['command'] is None: |
| 76 | self.rpc_response.is_error = True |
| 77 | self.rpc_response.node = ncerror.BadMsg(self.request_xml) |
| 78 | return |
| 79 | |
| 80 | except Exception as e: |
| 81 | self.rpc_response.is_error = True |
| 82 | self.rpc_response.node = ncerror.ServerException( |
| 83 | self.request_xml) |
| 84 | return |
| 85 | |
Khen Nursimulu | b21bd64 | 2017-02-20 21:32:27 -0500 | [diff] [blame] | 86 | def _parse_params(self, node): |
| 87 | params = {} |
| 88 | if node is not None: |
| 89 | for r in node: |
| 90 | children = r.getchildren() |
khenaidoo | 2d7af13 | 2017-03-23 15:45:51 -0400 | [diff] [blame] | 91 | tag = r.tag.replace(qmap(C.VOLTHA), "") |
Khen Nursimulu | b21bd64 | 2017-02-20 21:32:27 -0500 | [diff] [blame] | 92 | if children: |
khenaidoo | 2d7af13 | 2017-03-23 15:45:51 -0400 | [diff] [blame] | 93 | if tag in params: |
| 94 | if not isinstance(params[tag], list): |
| 95 | temp = [] |
| 96 | temp.append(params[tag]) |
| 97 | params[tag] = temp |
| 98 | params[tag].append(self._parse_params(children)) |
| 99 | else: |
| 100 | params[tag] = self._parse_params(children) |
Khen Nursimulu | b21bd64 | 2017-02-20 21:32:27 -0500 | [diff] [blame] | 101 | else: |
khenaidoo | 2d7af13 | 2017-03-23 15:45:51 -0400 | [diff] [blame] | 102 | # Convert string boolean to boolean |
| 103 | if r.text == 'true': |
| 104 | params[tag] = True |
| 105 | elif r.text == 'false': |
| 106 | params[tag] = False |
| 107 | else: |
| 108 | params[tag] = r.text |
Khen Nursimulu | b21bd64 | 2017-02-20 21:32:27 -0500 | [diff] [blame] | 109 | return params |
| 110 | |
Khen Nursimulu | 8ffb893 | 2017-01-26 13:40:49 -0500 | [diff] [blame] | 111 | def _extract_parameters(self): |
| 112 | try: |
| 113 | rpc_node = self.request_xml.find(''.join( |
| 114 | [qmap(C.VOLTHA), |
| 115 | self.request['command']]) |
| 116 | ) |
Khen Nursimulu | b21bd64 | 2017-02-20 21:32:27 -0500 | [diff] [blame] | 117 | |
| 118 | # Parse rpc the parameters |
| 119 | self.request['params'] = self._parse_params(rpc_node) |
Khen Nursimulu | 8ffb893 | 2017-01-26 13:40:49 -0500 | [diff] [blame] | 120 | |
| 121 | # Remove the subclass element in the request if it is present as |
| 122 | # it is not required for rpc calls |
| 123 | if self.request.has_key('subclass'): |
| 124 | self.request.pop('subclass', None) |
| 125 | |
| 126 | # Extract the service and method from the rpc command |
| 127 | command = self.request['command'].split('-') |
| 128 | if len(command) != 2: |
| 129 | log.debug('invalid-format', command=self.request['command']) |
| 130 | raise |
| 131 | |
| 132 | self.service = command[0] |
| 133 | self.method = command[1] |
| 134 | if self.request.has_key('metadata'): |
| 135 | self.metadata = self.request['metadata'] |
| 136 | |
| 137 | except Exception as e: |
| 138 | self.rpc_response.is_error = True |
| 139 | self.rpc_response.node = ncerror.BadMsg(self.request_xml) |
| 140 | log.exception('params-parsing-error', xml=self.request_xml, e=e) |