image builder
by Jan Provazník
ImageBuilder UI patch. Most of functionality should be done.
CSS patch will be tomorow (I hope), "summary" view patch is
not complete (polling build_status, Finish button,...).
14 years
Minor API fixes
by Michal Fojtik
Hi all,
These patches are just minor cosmetic fixed. I moved all methods
to ApplicationHelper from server.rb to keep in server.rb
clean Rabbit/Sinatra DSL.
Removed obsolete 'builder' gem which was used for generating XML output.
Right now we are using just plain HAML for this.
Also I moved DRIVER constant to 'driver.rb' to keep all driver-related
stuff in one place.
All responed_to calls/initialization stuff moved to respond_to.rb for same
reason as above.
I finally managed to get our validation error reporting to work. Which
means: no more exceptions when validation fails.
According to previous discussions with lutter I decreated API
version number from 1.0 to 0.1. Version 1.0 will appear again
once we will stabilize API.
These patches don't break anything important, they are just 'cosmetic'
fixes and code cleanup.
-- Michal
14 years
[PATCH aggregator] preliminary 'provider service quality' portlet
by Mo Morsi
most of the styling is done, all that remains is:
- including the actual graphs
- including the 'poor/good service' widget
- wiring up the arrow buttons to whatever their corresponding
actions are (clarification needed)
---
src/app/controllers/dashboard_controller.rb | 4 ++
src/app/views/dashboard/summary.haml | 20 ++++++++++++-
src/public/images/dashboard_summary_next.png | Bin 0 -> 412 bytes
src/public/images/dashboard_summary_prev.png | Bin 0 -> 375 bytes
src/public/stylesheets/components.css | 41 +++++++++++++++++++++++++-
5 files changed, 63 insertions(+), 2 deletions(-)
create mode 100644 src/public/images/dashboard_summary_next.png
create mode 100644 src/public/images/dashboard_summary_prev.png
diff --git a/src/app/controllers/dashboard_controller.rb b/src/app/controllers/dashboard_controller.rb
index ef89d95..3a9a6ed 100644
--- a/src/app/controllers/dashboard_controller.rb
+++ b/src/app/controllers/dashboard_controller.rb
@@ -32,6 +32,10 @@ class DashboardController < ApplicationController
end
def index
+ @providers = Provider.find(:all)
+
+ @is_admin = @current_user.permissions.collect { |p| p.role }.
+ find { |r| r.name == "Administrator" }
@hide_getting_started = cookies["#{(a)current_user.login}_hide_getting_started"]
@current_users_pool = Pool.find(:first, :conditions => ['name = ?', @current_user.login])
render :action => :summary
diff --git a/src/app/views/dashboard/summary.haml b/src/app/views/dashboard/summary.haml
index 4eeb58b..f3d6ab6 100644
--- a/src/app/views/dashboard/summary.haml
+++ b/src/app/views/dashboard/summary.haml
@@ -29,7 +29,7 @@
#actions_dashboard_section
%h2
Actions
- - if @current_user.permissions.collect { |p| p.role }.find { |r| r.name == "Administrator" }
+ - if @is_admin
%a{:href => url_for(:controller => "cloud_accounts", :action => "new")}
Add a Provider Account
%a{:href => url_for(:controller => "provider", :action => "new")}
@@ -44,6 +44,24 @@
%a{:href => url_for(:controller => "", :action => "")}
Enter a help ticket
+#service_quality_dashboard_section
+ - if @is_admin
+ %h2
+ Provider Service Quality
+ .dashboard_section_summary
+ Average time to submit tasks to provider, 24 hours
+ <img src="images/dashboard_summary_prev.png" /><img src="images/dashboard_summary_next.png" />
+ - @providers.each do |provider|
+ .provider_service_quality_graph
+ <!-- FIXME include graph -->
+ .provider_service_quality_graph_summary
+ = provider.name
+ <!-- FIXME 'good/poor/average service... -->
+ <div style="clear: both;" />
+ - else
+ %h2
+ Service Quality
+
:javascript
$("#hide_getting_started").click(function(){
$('#getting_started_dashboard_section').hide();
diff --git a/src/public/images/dashboard_summary_next.png b/src/public/images/dashboard_summary_next.png
new file mode 100644
index 0000000000000000000000000000000000000000..ae8b24a3fb0754caeabee6fc3ee2d0ee09d99570
GIT binary patch
literal 412
zcmV;N0b~A&P)<h;3K|Lk000e1NJLTq000;O000yS0ssI27}sjl00001b5ch_0Itp)
z=>Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RV1sM)0F!F(b!2kdOE=fc|R5;6}
zl)J5iFcgMOpx_}vB;*D}MacrtBf$V+0v13_kPS%B1i_voRZ2im(5H#Sqsjwui!`}W
zf)o68$2$7-`y9*6@puFj$g&I}WLcJ(rfIR|e!n+OGmfKS7%Q4M9LJfadA(k5w;Ms!
zbsf<q2m)DT+xFpb_$D1e)c1W51ZkSmiXLpY+bD|WugSgCo6Y8JA3~@oirsE!S=QTz
z*Y)eVKL2WxB=LR!`LM3*^?Lo=`un~Q!!XOTg)@4_aU9R{Xhm@xV~iC=ArBiN^jro(
zFf*NhOtWa3rfHh%x_O>|>Zz*gbUKl*=6N2*_|w+EO|;+dClZfDRNu&hvMg0qT~S(w
zVYpl_q9}61Ff6vTZF@eSA%p+`rYMTVB2g42N#c1P0PqJMO6kwB(fBq10000<MNUMn
GLSTZh>#cwQ
literal 0
HcmV?d00001
diff --git a/src/public/images/dashboard_summary_prev.png b/src/public/images/dashboard_summary_prev.png
new file mode 100644
index 0000000000000000000000000000000000000000..34ab07092795ddba41e3935920f7779f7dc50965
GIT binary patch
literal 375
zcmV--0f_#IP)<h;3K|Lk000e1NJLTq000*N000yS0ssI2>D)0{00001b5ch_0Itp)
z=>Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RV1sM)07{@dyI{*Ly2}wjjR5;6}
zl)(ywAP|P#iUh$!6ba#>lhFG=OcZp8Bs$b#CDO2BZxQX5;m&QG@gL`#!Iuz1Db=>^
zvMj*XJgqh7JV_Elh_#9{j$;r6|40A;oNe2D-@i{XHtQJg7eyhZG;q0zP197C<+`qB
zx>td|@9VmLI-{RmaL$Ke*iV|Kab0(J!!V4Z=uTyx=c=ksAWkmE`0g$9Jm-1-1jOBp
zAcS!o+w9B9Pm+W&cBEiQ7h{}d*^v&V6d|-Hd~fORNka%3WBa5KLf=Fm?XKr}X_`_>
zEjv0IAp~P=#N-+49En_Z1R)%T;h!%G0Pqq*bX}*EisSf6*-I4w!2A7{QfjU3R6at9
VdNubHEt&uT002ovPDHLkV1hsVmc0M~
literal 0
HcmV?d00001
diff --git a/src/public/stylesheets/components.css b/src/public/stylesheets/components.css
index 5b25cd4..b61fbc9 100644
--- a/src/public/stylesheets/components.css
+++ b/src/public/stylesheets/components.css
@@ -72,6 +72,22 @@ ul.nav li.selected {
}
/* dashboard style */
+.dashboard_section_summary {
+ background: #F2F2F2;
+ font-size: 0.8em;
+ font-weight: bolder;
+ margin: 0 15px 10px 0;
+ padding: 5px 0px 5px 5px;
+}
+
+.dashboard_section_summary img:first-child {
+ padding-left: 40px;
+}
+
+.dashboard_section_summary img {
+ vertical-align: middle;
+}
+
#getting_started_dashboard_section {
background: #F2F2F2;
width: 850px;
@@ -118,7 +134,6 @@ ul.nav li.selected {
width: 390px;
height: 100px;
border: 1px solid black;
- background: #F2F2F2;
padding: 5px 0 5px 15px;
margin: 10px 0px 10px 5px;
-moz-border-radius: 5px;
@@ -136,3 +151,27 @@ ul.nav li.selected {
color: blue;
text-decoration: underline;
}
+
+#service_quality_dashboard_section {
+ width: 390px;
+ border: 1px solid black;
+ padding: 5px 0 5px 15px;
+ margin: 10px 0px 10px 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+}
+
+.provider_service_quality_graph {
+ width: 100px;
+ height: 50px;
+ border: 1px solid black;
+ float: left;
+ margin: 0px 5px 0px 5px;
+}
+
+.provider_service_quality_graph_summary {
+ float: left;
+ width: 60px;
+ height: 15px;
+ padding: 20px 0 24px 0;
+}
--
1.6.2.5
14 years
['PATCH core'] Firewalling - v2 (with prototype for terremark - ec2 next) These patches implement a second version of firewalling for the terremark driver. This is still a prototype - we will try and see if this model 'fits' for ec2 before committing to using this (terremark and ec2 are the only clouds that require management of firewall rules in order to gain access to a given instance). Currently a firewall_rule consists of: public_ip, public_port, protocol, private_ip, private_port (t
by marios@redhat.com
From: marios <marios(a)redhat.com>
Current operations are list (index), create and delete a firewall rule. Also these patches contain only the html haml (not yet xml - want to decide if this is the model before doing this).
---
server/deltacloud.rb | 1 +
server/lib/deltacloud/base_driver/base_driver.rb | 16 +++
.../drivers/terremark/terremark_driver.rb | 100 +++++++++++++++++++-
server/lib/deltacloud/models/firewall_rule.rb | 9 ++
server/server.rb | 88 ++++++++++++++++--
server/views/firewall_rules/index.html.haml | 37 +++++++
server/views/firewall_rules/new.html.haml | 22 +++++
server/views/firewall_rules/show.html.haml | 21 ++++
8 files changed, 285 insertions(+), 9 deletions(-)
create mode 100644 server/lib/deltacloud/models/firewall_rule.rb
create mode 100644 server/views/firewall_rules/index.html.haml
create mode 100644 server/views/firewall_rules/new.html.haml
create mode 100644 server/views/firewall_rules/show.html.haml
diff --git a/server/deltacloud.rb b/server/deltacloud.rb
index 1c19a5d..561fdfb 100644
--- a/server/deltacloud.rb
+++ b/server/deltacloud.rb
@@ -12,3 +12,4 @@ require 'deltacloud/models/instance'
require 'deltacloud/models/instance_profile'
require 'deltacloud/models/storage_snapshot'
require 'deltacloud/models/storage_volume'
+require 'deltacloud/models/firewall_rule'
diff --git a/server/lib/deltacloud/base_driver/base_driver.rb b/server/lib/deltacloud/base_driver/base_driver.rb
index a2b3bbe..b334db1 100644
--- a/server/lib/deltacloud/base_driver/base_driver.rb
+++ b/server/lib/deltacloud/base_driver/base_driver.rb
@@ -154,6 +154,22 @@ module Deltacloud
def reboot_instance(credentials, id)
end
+ def firewall_rules(credentials, opts)
+ []
+ end
+
+ def firewall_rule(credentials, opts)
+ rules = firewall_rules(credentials, opts)
+ return rules.first unless rules.empty?
+ nil
+ end
+
+ def create_firewall_rule(credentials, opts)
+ end
+ def delete_firewall_rule(credentials, opts)
+ end
+
+
def storage_volume(credentials, opts)
volumes = storage_volumes(credentials, opts)
return volumes.first unless volumes.empty?
diff --git a/server/lib/deltacloud/drivers/terremark/terremark_driver.rb b/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
index ae3c554..d464052 100644
--- a/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
+++ b/server/lib/deltacloud/drivers/terremark/terremark_driver.rb
@@ -32,7 +32,7 @@ module Deltacloud
class TerremarkDriver < Deltacloud::BaseDriver
- feature :instances, :user_name
+# feature :instances, :user_name
#--
# Vapp State Map... for use with convert_instance (get an integer back from terremark)
@@ -50,6 +50,89 @@ VAPP_STATE_MAP = { "0" => "PENDING", "1" => "PENDING", "2" => "STOPPED", "4"
#storage_disks [1..15]
#--
+# FIREWALL RULES
+#--
+ def firewall_rules(credentials, opts=nil)
+ firewall_rules = []
+ terremark_client = new_client(credentials)
+ services = terremark_client.get_internet_services(terremark_client.default_vdc_id).body['InternetServices'].each do |service|
+ s_id = service['Id'].to_s
+ public_ip = service['PublicIpAddress']['Name']
+ public_port = service['Port']
+ protocol = service['Protocol']
+ nodes = terremark_client.get_node_services(s_id).body['NodeServices']
+ unless nodes.empty?
+ nodes.each do |node|
+ #puts "Id is #{node['Id']}, public_ip is #{public_ip}, public_port is #{public_port}, Private IP is #{node['IpAddress']}, private port is #{node['Port']} and protocol is #{protocol}"
+ firewall_rules << FirewallRule.new({ :id => s_id,
+ :public_address => public_ip,
+ :public_port => public_port,
+ :private_address => node['IpAddress'],
+ :private_port => node['Port'],
+ :protocol => protocol
+ })
+ end #nodes.each do
+ end #unless nodes empty
+ end #services.each do
+ firewall_rules = filter_on( firewall_rules, :id, opts )
+ firewall_rules
+ end
+
+#--
+# DELETE FIREWALL RULE
+#--can expect that the service ID is passed in the opts...
+ def delete_firewall_rule(credentials, opts=nil)
+ service_id = opts[:id].to_s
+ terremark_client = new_client(credentials)
+ nodes = terremark_client.get_node_services(service_id).body['NodeServices']
+ unless nodes.empty?
+ nodes.each do |node|
+ terremark_client.delete_node_service(node['Id'])
+ end
+ end
+ terremark_client.delete_internet_service(service_id)
+ end
+
+#--
+# CREATE NEW FIREWALL RULE
+#--expected input: private and public ip address, private and public ports, protocol
+#--opts['public_address']
+#--pts['service_protocol']
+#--opts['public_port']
+#--opts['private_port']
+#--opts['private_address']
+#--opts['service_name'] - OPTIONAL
+#--opts['node_name'] - OPTIONAL
+ def create_firewall_rule(credentials, opts=nil)
+ terremark_client = new_client(credentials)
+ public_address = opts['public_address']
+ public_port = opts['public_port']
+ protocol = opts['service_protocol']
+ #check if internet service exists or creating a new one
+ service_id = internet_service_exists(terremark_client, public_address, public_port, protocol)
+ unless service_id
+ ip_id = nil
+ #need to deduce the ip id to create a new internet service
+ ips = terremark_client.get_public_ips(terremark_client.default_vdc_id).body['PublicIpAddresses']
+ ips.each do |ip|
+ if (ip['name'] == public_address)
+ ip_id = ip['id'].to_s
+ break
+ end
+ end #end ips.each
+ service_name ||= opts['service_name']
+ service_name ||= "svc" + (rand(1000)*Time.now.to_i).to_s.slice(0,7)
+ service_id = terremark_client.add_internet_service(ip_id, service_name, protocol, public_port).body['Id'].to_s
+ end
+ #it adds the node service to the internet service...
+ node_name ||= opts['node_name']
+ node_name ||= "nod" + (rand(1000)*Time.now.to_i).to_s.slice(0,7)
+ private_address = opts['private_address']
+ private_port = opts['private_port']
+ terremark_client.add_node_service(service_id, private_address, node_name, private_port)
+ end
+
+#--
# IMAGES
#--
#aka "vapp_templates"
@@ -183,6 +266,21 @@ end
private
#--
+# INTERNET_SERVICE_EXISTS
+#-- helper to check if a given public IP/Port combination are defined as an existing internet service
+#-- used by the create_firewall_rule method
+def internet_service_exists(terremark_client, public_address, public_port, protocol)
+ services = terremark_client.get_internet_services(terremark_client.default_vdc_id)
+ services.body['InternetServices'].each do |current_service|
+ if ( (current_service['PublicIpAddress']['Name'] == public_address) && (current_service['Port'].to_s == public_port) &&
+ (current_service['Protocol'].upcase == protocol.upcase) )
+ return current_service['Id']
+ end
+ end
+ nil
+end
+
+#--
# CONVERT IMAGE
#--
#gets a vapp_template from a catalog and makes it a Image
diff --git a/server/lib/deltacloud/models/firewall_rule.rb b/server/lib/deltacloud/models/firewall_rule.rb
new file mode 100644
index 0000000..390ede3
--- /dev/null
+++ b/server/lib/deltacloud/models/firewall_rule.rb
@@ -0,0 +1,9 @@
+class FirewallRule < BaseModel
+
+ attr_accessor :public_address
+ attr_accessor :public_port
+ attr_accessor :private_address
+ attr_accessor :private_port
+ attr_accessor :protocol
+
+end
\ No newline at end of file
diff --git a/server/server.rb b/server/server.rb
index b5bdfac..cb15bdf 100644
--- a/server/server.rb
+++ b/server/server.rb
@@ -65,6 +65,8 @@ def show(model)
end
+
+
#
# Error handlers
#
@@ -108,7 +110,60 @@ get '/api\/?' do
end
end
+get '/api/firewall_rules/:id/destroy' do
+ method = "delete_firewall_rule"
+ not_found unless driver.respond_to?(method)
+ opts = {}
+ opts[:id] = params[:id]
+ driver.send(method, credentials, opts)
+ redirect firewall_rules_url
+end
+
+get '/api/firewall_rules/new' do
+ respond_to do |format|
+ format.html { haml :"firewall_rules/new" }
+ end
+end
+
+
+def delete_firewall_rule(service_id)
+ driver.send(delete_firewall_rule, credentials, {:id => params[:id]})
+end
+
# Rabbit DSL
+collection :firewall_rules do
+
+ description "Allow user to expose a public IP address/port and map these onto an internal IP address/port. eg expose ssh access [port 22, tcp]."
+ operation :index do
+ description 'Show all available network services'
+ control { filter_all(:firewall_rules) }
+ end
+
+ operation :show do
+ description 'Show a firewall rule identified by its id'
+ param :id, :string, :required
+ control { show(:firewall_rule) }
+ end
+
+ operation :create do
+ description 'Create a new firewall rule'
+ param :public_address, :string, :required
+ param :public_port, :string, :required
+ param :private_address, :string, :required
+ param :private_port, :string, :required
+ param :service_protocol, :string, :required
+ control do
+ driver.create_firewall_rule(credentials, params )
+ filter_all(:firewall_rules)
+ end
+ end
+
+ operation :destroy, :method => :post do
+ description 'destroy given firewall rule'
+ param :id, :string, :required
+ control { delete_firewall_rule(:id) }
+ end
+end
collection :realms do
description "Within a cloud provider a realm represents a boundary containing resources. The exact definition of a realm is left to the cloud provider. In some cases, a realm may represent different datacenters, different continents, or different pools of resources within a single datacenter. A cloud provider may insist that resources must all exist within a single realm in order to cooperate. For instance, storage volumes may only be allowed to be mounted to instances within the same realm."
@@ -186,6 +241,22 @@ collection :instance_states do
end
end
+# Special instance get operations that we only allow for HTML
+get "/api/instances/:id/:action" do
+ meth = :"#{params[:action]}_instance"
+ not_found unless driver.respond_to?(meth)
+ respond_to do |format|
+ format.html do
+ driver.send(meth, credentials, params[:id])
+ if ( (params[:action] == 'destroy') or (params[:action] == 'stop') )
+ redirect instances_url
+ else
+ redirect instance_url(params[:id])
+ end
+ end
+ end
+end
+
get "/api/instances/new" do
@instance = Instance.new( { :id=>params[:id], :image_id=>params[:image_id] } )
@image = driver.image( credentials, :id => params[:image_id] )
@@ -197,14 +268,15 @@ get "/api/instances/new" do
end
def instance_action(name)
- @instance = driver.send(:"#{name}_instance", credentials, params["id"])
-
- return redirect(instances_url) if name.eql?(:destroy) or @instance.class!=Instance
-
- respond_to do |format|
- format.html { haml :"instances/show" }
- format.xml { haml :"instances/show" }
- format.json {convert_to_json(:instance, @instance) }
+ @instance = driver.send(:"#{name}_instance", credentials, params[:id])
+ if name==:destroy
+ redirect instances_url
+ else
+ respond_to do |format|
+ format.html { haml :"instances/show" }
+ format.xml { haml :"instances/show" }
+ format.json {convert_to_json(:instance, @instance) }
+ end
end
end
diff --git a/server/views/firewall_rules/index.html.haml b/server/views/firewall_rules/index.html.haml
new file mode 100644
index 0000000..47990b0
--- /dev/null
+++ b/server/views/firewall_rules/index.html.haml
@@ -0,0 +1,37 @@
+%h1
+ Firewall Rules
+%h3
+ = link_to("Create new firewall rule", firewall_rules_url() + "/new")
+%table.display
+ %thead
+ %tr
+ %th
+ ID
+ %th
+ Public Address
+ %th
+ Public Port
+ %th
+ Private Address
+ %th
+ Private Port
+ %th
+ Protocol
+ %tbody
+ - if @firewall_rules
+ - for rule in @firewall_rules
+ %tr
+ %td
+ = link_to rule.id, firewall_rules_url()+"/#{rule.id}"
+ %td
+ = rule.public_address
+ %td
+ = rule.public_port
+ %td
+ = rule.private_address
+ %td
+ = rule.private_port
+ %td
+ = rule.protocol
+ %td
+ = link_to("destroy", firewall_rules_url()+"/#{rule.id}/destroy", {:method => :post})
\ No newline at end of file
diff --git a/server/views/firewall_rules/new.html.haml b/server/views/firewall_rules/new.html.haml
new file mode 100644
index 0000000..9c6f0a0
--- /dev/null
+++ b/server/views/firewall_rules/new.html.haml
@@ -0,0 +1,22 @@
+%h1 New Firewall Rule
+
+%form{ :action => firewall_rules_url, :method => :post }
+ %p
+ %label
+ Public Address:
+ %input{ :name => 'public_address', :size => 16 }
+ %label
+ Public Port:
+ %input{ :name => 'public_port', :size => 6}
+ %label
+ Protocol:
+ %input{ :name => 'service_protocol', :size => 5}
+ %p
+ %label
+ Private Address:
+ %input{ :name => 'private_address', :size => 16 }
+ %label
+ Private Port:
+ %input{ :name => 'private_port', :size => 6}
+ %p
+ %input{ :type => :submit, :name => 'commit', :value => "create" }
\ No newline at end of file
diff --git a/server/views/firewall_rules/show.html.haml b/server/views/firewall_rules/show.html.haml
new file mode 100644
index 0000000..8ec81c2
--- /dev/null
+++ b/server/views/firewall_rules/show.html.haml
@@ -0,0 +1,21 @@
+%h1 Firewall Rule
+%h2
+ = @firewall_rule.id
+
+%dl
+ %di
+ %dt Public IP
+ %dd
+ = @firewall_rule.public_address
+ %dt Public Port
+ %dd
+ = @firewall_rule.public_port
+ %dt Private IP
+ %dd
+ = @firewall_rule.private_address
+ %dt Private Port
+ %dd
+ = @firewall_rule.private_port
+ %dt Protocol
+ %dd
+ = @firewall_rule.protocol
\ No newline at end of file
--
1.6.6.1
14 years
[PATCH aggregator] JavaScript cleanup
by Tomas Sedovic
Howdy,
These two patches delete all the JavaScript code, libraries, layouts and views that are not used anymore.
Since the minified JS files have lines that are too long for poor git-send-email to handle, the patches are in this e-mail's attachment.
Thomas
14 years
Quota CRUD + Audit + Enforcement
by Martyn Taylor
This Series of patches adds the ability to Create/Edit/Delete quota on Pools and Cloud Accounts. It Audits quota by storing totals on the quota model. Then enforces the Quota on Instance Create/Start in TaskOMatic
Changes from last submission:
- Added Quota Factory
- Updated Quota limits/totals to use strings instead of integer (copying the hwp model)
- Refactory Model.find methods to use e.g. pool.quota
- Updated task-o-matic to check quota for start and create on create_instance, using assumption that all providers start instance on create
- Removed STATE_NEW from ACTIVE_STATES
14 years
image builder
by Jan Provazník
Hi,
this is first part of Image builder patch.
PATCH 1: Creates models and migrations for image builder, validations and tests are not completed yet.
PATCH 3: Temporary yaml config files with repository definitions.
PATCH 4: Controller and views for Image builder UI, TBD: package selections and summary page
14 years
[PATCH aggregator] Add GraphService to aggregator
by Steve Linabery
Create GraphService object to manage calls to forked gnuplot process
for chart generation. Also add Graph DTO for encapsulating svg or various
other chart description languages.
---
src/app/models/graph.rb | 9 ++++++
src/app/services/graph_service.rb | 50 +++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 0 deletions(-)
create mode 100644 src/app/models/graph.rb
create mode 100644 src/app/services/graph_service.rb
diff --git a/src/app/models/graph.rb b/src/app/models/graph.rb
new file mode 100644
index 0000000..16e609e
--- /dev/null
+++ b/src/app/models/graph.rb
@@ -0,0 +1,9 @@
+class Graph
+ attr :svg
+
+ QOS_AVG_TIME_TO_SUBMIT = "qos_avg_time_to_submit"
+
+ def initialize
+ @svg = ""
+ end
+end
diff --git a/src/app/services/graph_service.rb b/src/app/services/graph_service.rb
new file mode 100644
index 0000000..8fc5bad
--- /dev/null
+++ b/src/app/services/graph_service.rb
@@ -0,0 +1,50 @@
+class GraphService
+ require 'gnuplot'
+
+ def gnuplot_open( persist=false )
+ cmd = Gnuplot.gnuplot( persist ) or raise 'gnuplot not found'
+ output_stream = IO::popen( cmd, "r+")
+ end
+
+
+ def qos_avg_time_to_submit_graph ( provider=nil, width=200, height=100 )
+
+ graph = Graph.new
+ gp = gnuplot_open
+
+ Gnuplot::Plot.new( gp ) do |plot|
+ plot.terminal "svg size #{width},#{height}"
+ plot.arbitrary_lines << "unset xtics"
+ plot.arbitrary_lines << "unset x2tics"
+ plot.arbitrary_lines << "unset ytics"
+ plot.arbitrary_lines << "unset y2tics"
+
+ #FIXME: get data from DataService for the provider.
+ #First build three equal-length arrays
+ x = (0..20).collect { |v| v.to_f }
+ y = x.collect { |v| v ** 2 }
+ c = y.collect { |v| if v > 100 then 1 else 3 end }
+
+ #The three arrays above are three columns of data for gnuplot.
+ #'c' is used for the point's color. See gnuplot docs for
+ #'lc variable' usage.
+ plot.data << Gnuplot::DataSet.new( [x, y, c] ) do |ds|
+ ds.using = "1:2:3"
+ ds.with = "lines lc variable"
+ ds.notitle
+ end
+ end
+ gp.flush
+ gp.close_write
+ gp.read(nil,graph.svg)
+ gp.close_read
+ graph
+ end
+
+ def dashboard_qos (provider = nil)
+ graphs = Hash.new
+ graphs[Graph::QOS_AVG_TIME_TO_SUBMIT] = qos_avg_time_to_submit_graph(provider)
+ graphs
+ end
+
+end
--
1.6.6.1
14 years
CSS cleanup
by Tomas Sedovic
This patch removes styles that we no longer need. In addition, it drops more
of the ovirt legacy -- some layouts and helpers that we don't use anywhere in
the current code.
14 years