Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
OpnSense
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kulya
OpnSense
Commits
e160efa7
Commit
e160efa7
authored
May 26, 2015
by
Ad Schellevis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(trafficshaper) work in progress traffic shaper middleware and frontend components
parent
3926ad51
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
297 additions
and
76 deletions
+297
-76
SettingsController.php
...rollers/OPNsense/TrafficShaper/Api/SettingsController.php
+104
-4
IndexController.php
...pp/controllers/OPNsense/TrafficShaper/IndexController.php
+1
-0
dialogPipe.xml
...p/controllers/OPNsense/TrafficShaper/forms/dialogPipe.xml
+15
-0
TrafficShaper.php
...e/mvc/app/models/OPNsense/TrafficShaper/TrafficShaper.php
+43
-0
index.volt
src/opnsense/mvc/app/views/OPNsense/TrafficShaper/index.volt
+134
-72
No files found.
src/opnsense/mvc/app/controllers/OPNsense/TrafficShaper/Api/SettingsController.php
View file @
e160efa7
...
@@ -40,22 +40,122 @@ use \OPNsense\Base\UIModelGrid;
...
@@ -40,22 +40,122 @@ use \OPNsense\Base\UIModelGrid;
class
SettingsController
extends
ApiControllerBase
class
SettingsController
extends
ApiControllerBase
{
{
/**
/**
* retrieve pipe settings
* validate and save model after update or insertion
* @param $mdlShaper
* @param $node reference node, to use as relative offset
* @return array result / validation output
*/
private
function
savePipe
(
$mdlShaper
,
$node
)
{
$result
=
array
(
"result"
=>
"failed"
);
// perform validation
$valMsgs
=
$mdlShaper
->
performValidation
();
foreach
(
$valMsgs
as
$field
=>
$msg
)
{
if
(
!
array_key_exists
(
"validations"
,
$result
))
{
$result
[
"validations"
]
=
array
();
}
// replace absolute path to attribute for relative one at uuid.
$fieldnm
=
$msg
->
getField
();
$fieldnm
=
str_replace
(
$node
->
__reference
,
"pipe"
,
$fieldnm
);
$result
[
"validations"
][
$fieldnm
]
=
$msg
->
getMessage
();
}
// serialize model to config and save when there are no validation errors
if
(
$valMsgs
->
count
()
==
0
)
{
$mdlShaper
->
serializeToConfig
();
// save config if validated correctly
Config
::
getInstance
()
->
save
();
$result
[
"result"
]
=
"saved"
;
}
return
$result
;
}
/**
* retrieve pipe settings or return defaults
* @param $uuid item unique id
* @param $uuid item unique id
* @return array
* @return array
*/
*/
public
function
getPipeAction
(
$uuid
)
public
function
getPipeAction
(
$uuid
=
null
)
{
{
$mdlShaper
=
new
TrafficShaper
();
if
(
$uuid
!=
null
)
{
if
(
$uuid
!=
null
)
{
$mdlShaper
=
new
TrafficShaper
();
$node
=
$mdlShaper
->
getNodeByReference
(
'pipes.pipe.'
.
$uuid
);
$node
=
$mdlShaper
->
getNodeByReference
(
'pipes.pipe.'
.
$uuid
);
if
(
$node
!=
null
)
{
if
(
$node
!=
null
)
{
return
$node
->
getNodes
();
// return node
return
array
(
"pipe"
=>
$node
->
getNodes
());
}
}
}
else
{
// generate new node, but don't save to disc
$node
=
$mdlShaper
->
pipes
->
pipe
->
add
()
;
return
array
(
"pipe"
=>
$node
->
getNodes
());
}
}
return
array
();
return
array
();
}
}
/**
* update pipe with given properties
* @param $uuid item unique id
* @return array
*/
public
function
setPipeAction
(
$uuid
)
{
$result
=
array
(
"result"
=>
"failed"
);
if
(
$this
->
request
->
isPost
()
&&
$this
->
request
->
hasPost
(
"pipe"
))
{
$mdlShaper
=
new
TrafficShaper
();
if
(
$uuid
!=
null
)
{
$node
=
$mdlShaper
->
getNodeByReference
(
'pipes.pipe.'
.
$uuid
);
if
(
$node
!=
null
)
{
$node
->
setNodes
(
$this
->
request
->
getPost
(
"pipe"
));
return
$this
->
savePipe
(
$mdlShaper
,
$node
);
}
}
}
return
$result
;
}
/**
* add new pipe
* @return array
*/
public
function
addPipeAction
()
{
$result
=
array
(
"result"
=>
"failed"
);
if
(
$this
->
request
->
isPost
()
&&
$this
->
request
->
hasPost
(
"pipe"
))
{
$mdlShaper
=
new
TrafficShaper
();
$node
=
$mdlShaper
->
addPipe
();
$node
->
setNodes
(
$this
->
request
->
getPost
(
"pipe"
));
return
$this
->
savePipe
(
$mdlShaper
,
$node
);
}
return
$result
;
}
/**
* delete pipe by uuid
* @param $uuid item unique id
* @return array status
*/
public
function
delPipeAction
(
$uuid
)
{
$result
=
array
(
"result"
=>
"failed"
);
if
(
$this
->
request
->
isPost
())
{
$mdlShaper
=
new
TrafficShaper
();
if
(
$uuid
!=
null
)
{
if
(
$mdlShaper
->
pipes
->
pipe
->
del
(
$uuid
))
{
// if item is removed, serialize to config and save
$mdlShaper
->
serializeToConfig
();
Config
::
getInstance
()
->
save
();
$result
[
'result'
]
=
'deleted'
;
}
else
{
$result
[
'result'
]
=
'not found'
;
}
}
}
return
$result
;
}
/**
/**
* search traffic shaper pipes
* search traffic shaper pipes
* @return array
* @return array
...
...
src/opnsense/mvc/app/controllers/OPNsense/TrafficShaper/IndexController.php
View file @
e160efa7
...
@@ -37,6 +37,7 @@ class IndexController extends \OPNsense\Base\IndexController
...
@@ -37,6 +37,7 @@ class IndexController extends \OPNsense\Base\IndexController
public
function
indexAction
()
public
function
indexAction
()
{
{
$this
->
view
->
title
=
"Traffic Shaper"
;
$this
->
view
->
title
=
"Traffic Shaper"
;
$this
->
view
->
formDialogPipe
=
$this
->
getForm
(
"dialogPipe"
);
$this
->
view
->
pick
(
'OPNsense/TrafficShaper/index'
);
$this
->
view
->
pick
(
'OPNsense/TrafficShaper/index'
);
}
}
}
}
src/opnsense/mvc/app/controllers/OPNsense/TrafficShaper/forms/dialogPipe.xml
0 → 100644
View file @
e160efa7
<form>
<field>
<id>
pipe.bandwidth
</id>
<label>
bandwidth
</label>
<type>
text
</type>
<help>
test
</help>
</field>
<field>
<id>
pipe.bandwidthMetric
</id>
<label>
Enable traffic management.
</label>
<type>
dropdown
</type>
<help>
<![CDATA[test]]>
</help>
</field>
</form>
\ No newline at end of file
src/opnsense/mvc/app/models/OPNsense/TrafficShaper/TrafficShaper.php
View file @
e160efa7
...
@@ -32,4 +32,47 @@ use OPNsense\Base\BaseModel;
...
@@ -32,4 +32,47 @@ use OPNsense\Base\BaseModel;
class
TrafficShaper
extends
BaseModel
class
TrafficShaper
extends
BaseModel
{
{
/**
* Add new pipe to shaper, generate new number if none is given.
* The first 10000 id's are automatically reserved for internal usage.
* @param null $pipenr new pipe number
* @return ArrayField
*/
public
function
addPipe
(
$pipenr
=
null
)
{
$allpipes
=
array
();
foreach
(
$this
->
pipes
->
pipe
->
__items
as
$uuid
=>
$pipe
)
{
if
(
$pipenr
!=
null
&&
$pipenr
==
$pipe
->
number
->
__toString
())
{
// pipe found, return
return
$pipe
;
}
elseif
(
$pipenr
==
null
)
{
// collect pipe numbers to find first possible item
$allpipes
[]
=
$pipe
->
number
->
__toString
();
}
}
sort
(
$allpipes
);
if
(
$pipenr
==
null
)
{
// generate new pipe number
$newId
=
10000
;
for
(
$i
=
0
;
$i
<
count
(
$allpipes
);
++
$i
)
{
if
(
$allpipes
[
$i
]
>
$newId
&&
isset
(
$allpipes
[
$i
+
1
]))
{
if
(
$allpipes
[
$i
+
1
]
-
$allpipes
[
$i
]
>
1
)
{
// gap found
$newId
=
$allpipes
[
$i
]
+
1
;
break
;
}
}
elseif
(
$allpipes
[
$i
]
>=
$newId
)
{
// last item is higher than target
$newId
=
$allpipes
[
$i
]
+
1
;
}
}
}
else
{
$newId
=
$pipenr
;
}
$pipe
=
$this
->
pipes
->
pipe
->
add
();
$pipe
->
number
=
$newId
;
return
$pipe
;
}
}
}
src/opnsense/mvc/app/views/OPNsense/TrafficShaper/index.volt
View file @
e160efa7
...
@@ -34,8 +34,10 @@ POSSIBILITY OF SUCH DAMAGE.
...
@@ -34,8 +34,10 @@ POSSIBILITY OF SUCH DAMAGE.
$( document ).ready(function() {
$( document ).ready(function() {
/**
var grid =$("#grid-basic").bootgrid({
* Render pipe grid using searchPipes api
*/
var gridPipes =$("#grid-pipes").bootgrid({
ajax: true,
ajax: true,
selection: true,
selection: true,
multiSelect: true,
multiSelect: true,
...
@@ -49,32 +51,120 @@ POSSIBILITY OF SUCH DAMAGE.
...
@@ -49,32 +51,120 @@ POSSIBILITY OF SUCH DAMAGE.
}
}
});
});
grid.on("loaded.rs.jquery.bootgrid", function(){
/**
/* Executes after data is loaded and rendered */
* Link pipe grid command controls (edit/delete)
grid.find(".command-edit").on("click", function(e)
*/
gridPipes.on("loaded.rs.jquery.bootgrid", function(){
// edit item
gridPipes.find(".command-edit").on("click", function(e)
{
{
$('#form_uuid').attr('value',$(this).data("row-id"));
var uuid=$(this).data("row-id");
$('#myModal').modal();
mapDataToFormUI({'frm_DialogPipe':"/api/trafficshaper/settings/getPipe/"+uuid}).done(function(){
}).end().find(".command-delete").on("click", function(e)
// update selectors
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
// clear validation errors (if any)
clearFormValidation('frm_DialogPipe');
});
// show dialog for pipe edit
$('#DialogPipe').modal();
// curry uuid to save action
$("#btn_DialogPipe_save").unbind('click').click(savePipe.bind(undefined, uuid));
}).end();
// delete item
gridPipes.find(".command-delete").on("click", function(e)
{
{
alert("You pressed delete on row: " + $(this).data("row-id"));
var uuid = $(this).data("row-id");
BootstrapDialog.confirm({
title: 'Remove',
message: 'Remove selected item?',
type: BootstrapDialog.TYPE_DANGER,
btnCancelLabel: 'Cancel',
btnOKLabel: 'Yes',
btnOKClass: 'btn-primary',
callback: function(result) {
if(result) {
var url = "/api/trafficshaper/settings/delPipe/" + uuid;
ajaxCall(url=url,sendData={},callback=function(data,status){
// reload grid after delete
$("#grid-pipes").bootgrid("reload");
});
}
}
});
}).end();
});
/**
* save form data to end point for existing pipe
*/
function savePipe(uuid) {
saveFormToEndpoint(url="/api/trafficshaper/settings/setPipe/"+uuid,
formid="frm_DialogPipe", callback_ok=function(){
$("#DialogPipe").modal('hide');
$("#grid-pipes").bootgrid("reload");
});
}
/**
* save form data to end point for new pipe
*/
function addPipe() {
saveFormToEndpoint(url="/api/trafficshaper/settings/addPipe/",
formid="frm_DialogPipe", callback_ok=function(){
$("#DialogPipe").modal('hide');
$("#grid-pipes").bootgrid("reload");
});
}
/**
* Delete list of uuids on click event
*/
$("#deletePipes").click(function(){
BootstrapDialog.confirm({
title: 'Remove',
message: 'Remove selected items?',
type: BootstrapDialog.TYPE_DANGER,
btnCancelLabel: 'Cancel',
btnOKLabel: 'Yes',
btnOKClass: 'btn-primary',
callback: function(result) {
if(result) {
var rows =$("#grid-pipes").bootgrid('getSelectedRows');
if (rows != undefined){
var deferreds = [];
$.each(rows, function(key,uuid){
deferreds.push(ajaxCall(url="/api/trafficshaper/settings/delPipe/" + uuid, sendData={}));
});
// refresh after load
$.when.apply(null, deferreds).done(function(){
$("#grid-pipes").bootgrid("reload");
});
}
}
}
});
});
});
});
/**
* Add new pipe on click event
*/
$("#addPipe").click(function(){
mapDataToFormUI({'frm_DialogPipe':"/api/trafficshaper/settings/getPipe/"}).done(function(){
// update selectors
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
// clear validation errors (if any)
clearFormValidation('frm_DialogPipe');
});
$("#test").click(function(){
// show dialog for pipe edit
var rows =$("#grid-basic").bootgrid('getSelectedRows');
$('#DialogPipe').modal();
alert(rows);
// curry uuid to save action
$("#grid-basic").bootgrid("reload");
$("#btn_DialogPipe_save").unbind('click').click(addPipe);
setFormData('testfrm')
// var rowIds = [];
// for (var i = 0; i < rows.length; i++)
// {
// rowIds.push(rows[i]);
// }
// alert("Select: " + rowIds.join(","));
//alert(JSON.stringify($("#grid-basic").bootgrid('getSelectedRows')));
});
});
});
});
...
@@ -82,63 +172,35 @@ POSSIBILITY OF SUCH DAMAGE.
...
@@ -82,63 +172,35 @@ POSSIBILITY OF SUCH DAMAGE.
</script>
</script>
<table id="grid-
basic
" class="table table-condensed table-hover table-striped">
<table id="grid-
pipes
" class="table table-condensed table-hover table-striped">
<thead>
<thead>
<tr>
<tr>
<th data-column-id="number" data-type="number">Number</th>
<th data-column-id="number" data-type="number">Number</th>
<th data-column-id="bandwidth" data-type="number">Bandwidth</th>
<th data-column-id="bandwidth" data-type="number">Bandwidth</th>
<th data-column-id="bandwidthMetric" data-type="string">BandwidthMetric</th>
<th data-column-id="bandwidthMetric" data-type="string">BandwidthMetric</th>
<th data-column-id="description" data-type="string">description</th>
<th data-column-id="description" data-type="string">description</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">Commands</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">Commands</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">ID</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">ID</th>
</tr>
</tr>
</thead>
</thead>
<tbody>
<tbody>
</tbody>
</tbody>
<tfoot>
<tfoot>
<th></th>
<tr>
<th></th>
<td></td>
<th></th>
<td></td>
<th></th>
<td></td>
<th><button id="test">test</button></th>
<td></td>
<td></td>
<td>
<button type="button" id="addPipe" class="btn btn-xs btn-default"><span class="fa fa-pencil"></span></button>
<button type="button" id="deletePipes" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button>
</td>
</tr>
</tfoot>
</tfoot>
</table>
</table>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
{# include dialogs #}
<div class="modal-dialog">
{{ partial("layout_partials/base_dialog",['fields':formDialogPipe,'id':'DialogPipe','label':'Edit pipe'])}}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
<form id="testfrm">
<input id="form_uuid">
<table class="table table-striped table-condensed table-responsive">
<colgroup>
<col class="col-md-3"/>
<col class="col-md-4"/>
<col class="col-md-5"/>
</colgroup>
<tbody>
{{ partial("layout_partials/form_input_tr",
['id': 'general.port',
'label':'port',
'type':'text',
'help':'kjdhkjashdkjds'
])
}}
</tbody>
</table>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment