except KeyError:
                    reply[path] = data['error']
            request.sdata.add_to_push_queue('explorer', text=dumps(reply))
            request.sdata.log('got reply {}'.format(paths))

        reqs = map(request.sdata.api.get_schema, paths)
        d = defer.gatherResults(reqs)
        d.addCallback(got_data)

        request.setHeader('Content-Type', 'application/json')
        return '{}'

html = '''\
<h1 id="explorer_title" style="display: table-cell; width: 300px">Schema Explorer</h1>
<div id="explorer_show_hide" style="display: table-cell; transform: translateY(-10%);">
  <button id="explorer_show_hide_button" type="button">Show</button>
</div>
<div id="explorer_body">
    <div id="explorer_form_explanation">
      When you click on a path below, it will fill in the most recently clicked on or created path box.
    </div>
    <span class="spinner" id="spinner_explorer"></span>
    <div id="explorer_wrapper" style="height: ; overflow: auto;"> <!-- style is to make scrollable in telemetry tab -->
      <pre id="explorer_display"></pre>
      <div id="explorer_root"></div>
    </div>
</div>
'''

page = RegisterPage(ExplorerTab, path="/explorer", tab="explorer")
Example #2
0
        d.addCallback(request_protobufs)

        def get_protobufs(replies):
            line = '-' * 77
            sep = '\n//\n// ' + line + '\n//\n\n'
            text = sep.join([reply[1]['result'] for reply in replies])
            request.sdata.set_text('#protobuf_result', text)
            request.sdata.add_to_push_queue('stop_current_spinner')
            request.sdata.highlight('#protobuf_result')

        d.addCallback(get_protobufs)

        request.setHeader('Content-Type', 'application/json')
        return '{}'


html = '''\
<h1>Candidate Protocol Buffer definition</h1>
<form class="ajax_form" action="protobuf" method="post">
  <input type="text" name="path" size="120" placeholder="Enter path or show command here..." />
  <input type="submit" value="Go!" />
</form>
<span class="spinner" id="spinner_protobuf"></span>
<hr />
<h3>Result: <span id="protobuf_success"></span></h3>
<pre id="protobuf_result"></pre>
'''

page = RegisterPage(ProtobufTab, path="/protobuf", tab="protobuf")
        path = request.args['path'][0]  # Path to be queried
        fmt = request.args['format'][0]  # Requested data format
        d = request.sdata.api.get(path)

        def got_reply(reply):
            text = process_reply(reply, fmt == 'nest')
            request.sdata.add_to_push_queue('get', text=text)
            request.sdata.highlight('#get_result')
            request.sdata.log('got reply id {}'.format(reply['id']))

        d.addCallback(got_reply)
        request.setHeader('Content-Type', 'application/json')
        return '{}'


html = '''\
<h1>Get</h1>
<form class="ajax_form" action="get" method="post">
  <input type="text" name="path" id="get_input" size="120" placeholder="Enter path here..." />
  <input type="submit" value="Go!" />
  <input type="radio" name="format" value="list" checked><span>List</span>
  <input type="radio" name="format" value="nest"><span>Nest</span>
</form>
<span class="spinner" id="spinner_get"></span>
<hr />
<h3>Result: <span id="get_success"></span></h3>
<pre id="get_result"></pre>
'''

page = RegisterPage(GetTab, path="/get", tab="get")
Example #4
0
# =============================================================================
# render_about.py
#
# This file implements the `About` tab.
#
# December 2015
#
# Copyright (c) 2015 by cisco Systems, Inc.
# All rights reserved.
# =============================================================================

from m2m_demo.frontend import RegisterPage, BaseResource

class AboutTab(BaseResource):
    """
    About tab
    """
    def render_tab(self, request):
        self.has_debug_panel = False
        return help_html

help_html = '''\
<h1>About this app</h1>
<img src="about1.png" alt="about pic" class="about_pic"/>
<img src="about2.png" alt="about pic" class="about_pic"/>
<img src="about3.png" alt="about pic" class="about_pic"/>
'''

page = RegisterPage(AboutTab, tab="about")
Example #5
0
        def run_script(script):
            try:
                exec script in script_env
            except:
                exception_info = sys.exc_info()
                buf.extend(traceback.format_exception(*exception_info))
            request.sdata.log('got reply {}'.format(buf))
            request.sdata.add_to_push_queue('script', text=dumps(buf))

        script = request.args['script'][0]
        reactor.callInThread(run_script, script)


html = '''\
<h1>Run script</h1>
<form id="script_form" class="ajax_form" action="script" method="post">
  <textarea form="script_form" name="script" id="script_box" rows="10" cols="120" placeholder="Enter script here..."></textarea>
  <input type="submit" value="Go!" />
</form>
<div class="script_loader">
Examples
<ul>{}</ul>
</div>
<span class="spinner" id="spinner_script"></span>
<hr />
<h3>Result: <span id="script_success"></span></h3>
<pre id="script_result"></pre>
'''

page = RegisterPage(ScriptTab, path="/script", tab="script")
Example #6
0

def get_policy_contents(cfg, filename):
    return policies[filename]


def maybe_load_policies(cfg, policies_dict):
    # Update policies_dict with files found in /src/assets/policies
    policy_dir = os.path.join(cfg['assets'], 'policies')
    for root, dirs, files in os.walk(policy_dir):
        for filename in files:
            contents = open(os.path.join(root, filename)).read()
            policies_dict[filename] = contents
    return policies_dict


class PoliciesPage(BaseResource):
    """
    Serve up policies as a json object
    """
    def render_GET(self, request):
        request.setHeader('Content-Type', 'application/json')
        temp_pols = maybe_load_policies(self.cfg, policies)

        global policies
        policies = temp_pols
        return json.dumps(policies)


page = RegisterPage(PoliciesPage, '/policies')
Example #7
0
<span class="label">Interface:</span>
<input type="text" name="interface" size="42" value="GigabitEthernet0/0/0/5" />
</div>
<div>
<span class="label">Description:</span>
<input type="text" name="description" size="42" value="to PHX" />
</div>
<div>
<span class="label">IPv4 address:</span>
<input type="text" name="ipv4_addr" size="15" value="10.5.128.6" />
mask:
<input type="text" name="ipv4_mask" size="15" value="255.255.255.252" />
</div>
<textarea name="extra_cli" rows="4" cols="43"
 placeholder="Additional config in CLI form"></textarea>
<div class="buttons">
<input type="submit" id="update_json_input" name="action" value="Update JSON">
<input type="submit" name="action" value="Show changes">
<input type="submit" name="action" value="Commit">
<input type="submit" name="action" value="Replace subtree">
<input type="submit" name="action" value="Replace all">
</div>
</form>
<span class="spinner" id="spinner_manage_intf"></span>
<hr />
<h3>Result:</h3>
<div id="manage_intf_success"></div>
'''

page = RegisterPage(ManageIntfTab, path="/manage_intf", tab="manage_intf")
FEATURES['features'].add_blurb('Enable/disable the component features of the app.')
FEATURES['simple_cli'].add_blurb('Execute CLI show commands (equivalent to CLI on the router).')
FEATURES['json_cli'].add_blurb('Execute CLI show commands, but get structured data in response.')
FEATURES['get'].add_blurb('Get manageability data for a given schema path.')
FEATURES['schema'].add_blurb('Get schema information for a given schema path.')
FEATURES['script'].add_blurb('Write and execute Python scripts using the M2M API.')
FEATURES['explorer'].add_blurb('Explore the schema.')
FEATURES['write_file'].add_blurb('Write a file to disk on the connected IOS-XR device.')
FEATURES['telemetry'].add_blurb('Generate policy files for use with Telemetry.<br>Note that this feature is relevant to Telemetry in IOX-XR 6.0.0 only, the process has changed in 6.1.0')
FEATURES['gpb'].add_blurb('Construct a Google Protocol Buffer from a candidate file.<br> Note that this feature is relevant to Telemetry in IOX-XR 6.0.0 only, the process has changed in 6.1.0')
FEATURES['history'].add_blurb('Examine the commit history.')
FEATURES['current_config'].add_blurb('Calculate the mapping between the current config and equivalent schema paths and values.')
FEATURES['manage_intf'].add_blurb('Manage an interface.')
FEATURES['protobuf'].add_blurb('Generate a candidate Google Protocol Buffer from a schema path or show command.')
FEATURES['about'].add_blurb('Information about M2M.')

html = '''\
<h1>Features</h1>
''' + '\n'.join([
    '<input type="checkbox" value="{0}"{1}{2}>{3}{4}'.format(
        name,
        ' checked' if feature.enabled else '',
        ' disabled' if feature.immutable else '',
        feature.name,
        feature.blurb)
    for name, feature in FEATURES.iteritems()
])


page = RegisterPage(FeaturesTab, path="/features", tab="features")
    """
    def render_tab(self, request):
        return html

    def render_POST(self, request):
        cmd = request.args['cmd'][0]
        d = request.sdata.api.cli_exec(cmd)

        def got_reply(reply):
            request.sdata.add_to_push_queue('simple_cli', text=dumps(reply))
            request.sdata.log('got reply id {}'.format(reply['id']))

        d.addCallback(got_reply)
        request.setHeader('Content-Type', 'application/json')
        return '{}'


html = '''\
<h1>Simple CLI</h1>
<form class="ajax_form" action="simple_cli" method="post">
  <input type="text" name="cmd" id="simple_cli_input" size="120" placeholder="Enter command here..." />
  <input type="submit" value="Go!" />
</form>
<span class="spinner" id="spinner_simple_cli"></span>
<hr />
<h3>Result: <span id="simple_cli_success"></span></h3>
<pre id="simple_cli_result"></pre>
'''

page = RegisterPage(SimpleCliTab, path="/simple_cli", tab="simple_cli")
Connection status: <span id="connection_status"></span>
<img id="connection_loader" src="loader-red-circle.gif" alt="loading" />
<span id="connection_failure_reason"></span>
<button id="disconnect">Disconnect</button>
</div>
<form name="start_connection" id="start_connection" action="connection" method="post">
<fieldset id="connection_fieldset">
XR router address:
<input type="text" name="host" value="{host}" size="25">
<input type="submit" value="Connect">
<button id="toggle_creds">Credentials</button>
<div id="creds">
<span class="label">Username:</span>
<input type="text" name="username" value="{username}" size="30">
<span class="label">Secret:</span>
<input type="text" name="secret" value="{secret}" size="30">
<span class="label">Type:</span>
<input type="radio" name="secret_type" id="radio1" value="key" {secret_key}>
<label for="radio1">SSH key</label>
<input type="radio" name="secret_type" id="radio2" value="password" {secret_password}>
<label for="radio2">Password</label>
<span class="label">Port:</span>
<input type="text" name="port" value="{port}" size="10">
</div></fieldset></form>
<form class="ajax_form" action="yang_mode" id="yang_mode" method="post">
<input type="submit" value="Yang mode">
</form>
'''

page = RegisterPage(ConnectionTab, path="/connection", tab="connection")
                    row_style = ""
                row = '<tr {}><td><button id="toggle_{}">X</button></td>'.format(row_style, commit_id)
                for h in main_headings:
                    row += '<td>{}</td>'.format(entry[h])
                table += row + '</tr>\n'
                row = '<tr class="subrow" id="subrow_{}"><td colspan=4></a>'.format(commit_id)
                for h in sub_headings:
                    if entry[h] != "":
                        row += '<span><b>{}:</b> {}</span>'.format(h, entry[h])
                table += row + '<pre id="cfg_diff_{}"></pre></td></tr>\n'.format(commit_id)
                commit_ids.append(entry['Commit ID'])
            html = thead + table + '</div>'
            request.sdata.add_to_push_queue('set_html',
                                            selector='#cfg_hist_output',
                                            html=html)
            request.sdata.add_to_push_queue('commit_history_updates')
            for commit_id in commit_ids:
                self.render_single_diff(request, commit_id)
        d = request.sdata.api.cli_exec('show configuration history commit reverse detail')
        d.addCallback(done)
        return '{}'

tab_html = '''\
<h1>Configuration commit history</h1>
    <form class="ajax_form" action="history" method="post">
    <input type="submit" value="Update" /></form>
<div id="cfg_hist_output"></div>
'''

page = RegisterPage(ConfigHistoryPage, path='/history', tab='history')
        d.addCallback(got_reply)
        request.setHeader('Content-Type', 'application/json')
        return '{}'


html = '''\
<h1>Telemetry GPB</h1>
<form class="ajax_form" id="gpb_form" action="gpb" method="post">
    <span class="label">Path:</span>
    <input type="text" id="gpb_path" name="gpb_path" size="50"/>
    <input type="button" id="gpb_path_button" value="Get Candidate File"/>
    <span class="spinner" id="spinner_gpb"></span>
</form>
<br><br>

<div id="proto_editor_wrapper">
    <hr>
    <h2>Edit Proto File</h2>
    <div id="proto_editor"></div>
</div>

<div id="gpb_result_wrapper">
    <hr />
    <h2>Generated file <span id="gpb_success"></span></h2>
    <pre id="gpb_result"></pre>
</div>
'''

page = RegisterPage(GPBTab, path="/gpb", tab="gpb")
        cmd = request.args['cmd'][0]
        fmt = request.args['format'][0]  # Requested data format
        d = request.sdata.api.cli_get(cmd)

        def got_reply(reply):
            text = process_reply(reply, fmt == 'nest')
            request.sdata.add_to_push_queue('json_cli', text=text)
            request.sdata.highlight('#json_cli_result')
            request.sdata.log('got reply id {}'.format(reply['id']))

        d.addCallback(got_reply)
        request.setHeader('Content-Type', 'application/json')
        return '{}'


html = '''\
<h1>JSON CLI</h1>
<form class="ajax_form" action="json_cli" method="post">
  <input name="cmd" id="json_cli_input" type="text" size="120" placeholder="Enter command here..." />
  <input type="submit" value="Go!" />
  <input type="radio" name="format" value="list" checked><span>List</span>
  <input type="radio" name="format" value="nest"><span>Nest</span>
</form>
<span class="spinner" id="spinner_json_cli"></span>
<hr />
<h3>Result: <span id="json_cli_success"></span></h3>
<pre id="json_cli_result"></pre>
'''

page = RegisterPage(JsonCliTab, path="/json_cli", tab="json_cli")
Example #14
0
                if len(info_paths):
                    text = "Requires parent: " + '\n'.join(info_paths)
                    info_td = '''<img class="info" src="info.png" title='{}' alt="" />'''.format(text)
                else:
                    info_td = ''
                output.append('<tr><td class="cli">{}</td>' \
                              '<td class="path">{}</td>'
                              '<td class="path">{}</td></tr>'. \
                              format(cli_td, info_td, json_td))
        output.append('</table>')
        return '\n'.join(output)


html = '''\
<h1>Current configuration</h1>
<div class="toggle_cli_or_json">
  Show/hide:
  <br><input type="checkbox" name="toggle_cli" checked>CLI
  <br><input type="checkbox" name="toggle_path" checked>JSON paths
  <br><input type="checkbox" name="toggle_value" checked>JSON values
</div>
<form class="ajax_form" action="current_config" method="post">
  <input type="submit" value="Update" />
  <span class="spinner" id="spinner_current_config"></span>
  <span id="current_config_progress"></span>
</form>
<div id="current_config_result"></div>
'''

page = RegisterPage(CurrentConfigTab, path="/current_config", tab="current_config")
Example #15
0
from twisted.web import server
from m2m_demo.frontend import RegisterPage, BaseResource


class PushQueuePage(BaseResource):
    '''
    Serve up the push queue
    '''
    def render_POST(self, request):
        request.setHeader('Content-Type', 'application/json')
        pq = request.sdata.drain_push_queue()
        if len(pq) > 0:
            return json.dumps(pq)
        else:

            def finish_later(pq):
                try:
                    request.write(json.dumps(pq))
                    request.finish()
                except exceptions.RuntimeError as e:
                    print("### can't send push queue: ", e)
                    request.sdata.restore_push_queue(pq)

            request.sdata.add_pending_push_queue_dispatch(finish_later)
            request.notifyFinish().addErrback(
                lambda _: request.sdata.remove_pending_push_queue_dispatch())
            return server.NOT_DONE_YET


page = RegisterPage(PushQueuePage, '/push_queue')
Example #16
0
# =============================================================================
# render_yang_mode.py
#
# This file implements the Yang mode callback.
#
# December 2015
#
# Copyright (c) 2015 by cisco Systems, Inc.
# All rights reserved.
# =============================================================================

from m2m_demo.frontend import RegisterPage, BaseResource


class YangModeCallback(BaseResource):
    def render_POST(self, request):
        print('### starting yfw mode')
        request.sdata.api.yfw()
        request.setHeader('Content-Type', 'application/json')
        return '{}'


page = RegisterPage(YangModeCallback, path="/yang_mode")
    maybe_load_scriptlets(cfg)
    return scriptlets.keys()


def maybe_load_scriptlets(cfg):
    if scriptlets is not None:
        return
    global scriptlets
    scriptlets = OrderedDict()
    scriptlet_dir = os.path.join(cfg['assets'], 'scriptlets')
    for root, dirs, files in os.walk(scriptlet_dir):
        for filename in files:
            contents = open(os.path.join(root, filename)).read()
            m = re.search('_(.*)\.py', filename)
            if m:
                filename = m.group(1)
            scriptlets[filename] = contents


class ScriptletsPage(BaseResource):
    """
    Serve up scriptlets as a json object
    """
    def render_GET(self, request):
        request.setHeader('Content-Type', 'application/json')
        maybe_load_scriptlets(self.cfg)
        return json.dumps(scriptlets)


page = RegisterPage(ScriptletsPage, '/scriptlets')
  </div>
  <div>
    <textarea name="policy" id="telemetry_policy_contents" rows="6" onchange='M2M.fill_builder()' placeholder="Enter policy file here..."></textarea>
    <br>
    <span class="label">Add config?</span>
    <input type="checkbox" name="do_config" id="do_config" checked>
    <span class="label">Destination:</span>
    <input type="text" name="destination_ip" id="destination_ip" size="15">
    <span class="label">Port:</span>
    <input type="text" name="destination_port" id="destination_port" size="5">
    <input type="submit" value="Write to router" style="float: right;" />
  </div>
</form>
<div class="policy_loader">
  <h4>Load Example Policy</h4>
  <div class="preloaded_policies" name="preloaded_policies">
    <ul>{}</ul>
  </div>
  <h4>Upload Policy From File System</h4>
  <div>
    <input type='file' id='telemetry_policy_upload' onchange='M2M.get_contents_from_uploaded_policy()'>
  </div>
</div>
<span class="spinner" id="spinner_telemetry"></span>
<hr />
<h3>Result: <span id="telemetry_success"></span></h3>
<pre id="telemetry_result"></pre>
'''

page = RegisterPage(TelemetryTab, path="/telemetry", tab="telemetry")
            if 'message' in keys and \
               'get_keys is not supported for leaf nodes' in keys['message']:
                keys = 'No keys (leaf node)'
            return (schema, keys)

        d.addCallback(canonicalize)
        d.addCallback(send_response)

        # For now, just send back an empty response.
        request.setHeader('Content-Type', 'application/json')
        return '{}'


html = '''\
<h1>Schema</h1>
<form class="ajax_form" action="schema" method="post">
  <input type="text" name="path" id="schema_input" size="120" placeholder="Enter path here..." />
  <input type="submit" value="Go!" />
</form>
<span class="spinner" id="spinner_schema"></span>
<hr />
<div>
<h3>Schema:</h3>
<pre id="schema_result_schema"></pre>
<h3>Keys:</h3>
<pre id="schema_result_keys"></pre>
</div>
'''

page = RegisterPage(SchemaTab, path="/schema", tab="schema")
Example #20
0

class HomePage(BaseResource):
    """
    Home page. This is bolted together from a big static head fetched from
    a file, dynamic contributions from each plugin with a tab, and a static tail.
    """
    def __init__(self, cfg):
        BaseResource.__init__(self, cfg)
        index_html_path = os.path.join(self.cfg['assets'],
                                       'fragments/index.html')
        with open(index_html_path) as f:
            self.index_html_base = f.read()

    def render_GET(self, request):
        parts = [self.index_html_base]
        for tab, resource in self.cfg['tab_map'].items():
            parts.append('<div class="tab" id="{}">'.format(tab))
            tab_plugin = resource(self.cfg)
            parts.append(tab_plugin.render_tab(request))
            if tab_plugin.has_debug_panel:
                parts.append(
                    '<div class="debug" id="{}_debug"><table></table></div>'.
                    format(tab))
            parts.append('</div>')
        parts.append('</div></div></body></html>')
        return '\n'.join(parts)


page = RegisterPage(HomePage, '/')