<VirtualHost *:80>
- WSGIScriptAlias / /usr/share/unfold/apache/myslice.wsgi
- <Directory /usr/share/unfold/apache>
- <Files myslice.wsgi>
+ WSGIScriptAlias / /usr/share/unfold/myslice/wsgi.py
+ <Directory /usr/share/unfold/myslice>
+ <Files wsgi.py>
Order deny,allow
Allow from all
</Files>
usr/share/unfold/debug_platform
manage.py usr/share/unfold/
apache/myslice.conf /etc/apache2/sites-available
-apache/myslice.wsgi usr/share/unfold/apache
def __init__(self, auth=None, cainfo=None):
- config = Config()
self.auth = auth
self.cainfo = cainfo
self.errors = []
self.trace = []
self.calls = {}
self.multicall = False
+ config = Config()
self.url = config.manifold_url()
self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
expires: false,
speed: 1000
});
-*/
+*/
}
if (manifold.asynchroneous_debug)
messages.debug ("========== asynchroneous_success " + query.object + " -- before process_query_records");
from ConfigParser import RawConfigParser
from myslice.settings import ROOT
-# myslice/myslice.ini
-# as this code suggests, you have the option to write myslice/myslice.ini
+# as this code suggests, you have the option to override these defaults
+# by writing a file myslice/myslice.ini
# that looks like this
#[manifold]
#url = http://manifold.pl.sophia.inria.fr:7080/
#admin_user = admin
#admin_password = admin
-class Config:
+# use a singleton instead of staticmethods
+from manifold.util.singleton import Singleton
+
+class Config(object):
+ __metaclass__ = Singleton
# the OpenLab-wide backend as managed by UPMC
# xxx production should probably use https of course
# the INRIA setup is with "http://manifold.pl.sophia.inria.fr:7080/"
default_manifold_admin_user = 'admin'
- default_manifold_admin_password = None
-
- _config_parser = None
-
- # having grown tired of screwing up with git stashes
- # taking away my local config, we now more properly use
- # an external config file to override teh default
- # XXX we might use support from manifold util classes --jordan
- @staticmethod
- def manifold_url ():
- if Config._config_parser:
- return Config._config_parser.get('manifold','url')
- config = RawConfigParser ()
- config.add_section('manifold')
- config.set ('manifold', 'url', Config.default_manifold_url)
- config.read (os.path.join(ROOT,'myslice/myslice.ini'))
- Config._config_parser=config
- return Config.manifold_url()
-
- @staticmethod
- def manifold_admin_user_password():
- if Config._config_parser:
- admin_user = Config._config_parser.get('manifold','admin_user')
- admin_password = Config._config_parser.get('manifold','admin_password')
- return (admin_user, admin_password)
- config = RawConfigParser ()
- config.add_section('manifold')
- config.set ('manifold', 'admin_user', Config.default_manifold_admin_user)
- config.set ('manifold', 'admin_password', Config.default_manifold_admin_password)
- config.read (os.path.join(ROOT,'myslice/myslice.ini'))
- Config._config_parser=config
- return Config.manifold_admin_user_password()
+ default_manifold_admin_password = 'demo'
+
+
+ def __init__ (self):
+ parser = RawConfigParser ()
+ parser.add_section('manifold')
+ parser.set ('manifold', 'url', Config.default_manifold_url)
+ parser.set ('manifold', 'admin_user', Config.default_manifold_admin_user)
+ parser.set ('manifold', 'admin_password', Config.default_manifold_admin_password)
+ parser.read (os.path.join(ROOT,'myslice/myslice.ini'))
+ self.config_parser=parser
+
+ def manifold_url (self):
+ return self.config_parser.get('manifold','url')
+
+ def manifold_admin_user_password(self):
+ return (self.config_parser.get('manifold','admin_user'),
+ self.config_parser.get('manifold','admin_password'))
# exporting these details to js
- @staticmethod
- def manifold_js_export ():
- return "var MANIFOLD_URL = '%s';\n"%Config.manifold_url();
+ def manifold_js_export (self):
+ return "var MANIFOLD_URL = '%s';\n"%self.manifold_url();
on_filter_added: function(filter)
{
// XXX
+ console.log(filter);
this.redraw_table();
},
from unfold.plugin import Plugin
-class Slicestat(Plugin):
+class SliceStat(Plugin):
def __init__ (self, query, **settings):
Plugin.__init__ (self, **settings)
def requirements (self):
reqs = {
'js_files' : [
- 'js/date.js',
- 'js/slicestat.js'
+
+ 'js/slicestat.js',
+
],
'css_files': [
'css/slicestat.css',
+iframe#slicestat_resource {
+ width:100%;
+ height:400px;
+ border:0;
+ overflow: hidden;
+}
(function($){
- var Slicestat = Plugin.extend({
+ var SliceStat = Plugin.extend({
/** XXX to check
* @brief Plugin constructor
*/
init: function(options, element) {
// Call the parent constructor, see FAQ when forgotten
- this._super(options, element);
-
- google.load("visualization", "1.0", {packages:["corechart"]});
-
+ this._super(options, element);
/* Member variables */
{
console.log(record);
- var node = record.hostname;
- var slice = 'root';
-
- google.setOnLoadCallback(function() {
-
- var options = {
- pointSize: 2,
- lineWidth: 1,
- title: 'Slice '+slice+' last 24 hours', 'width':780, 'height':400,
- vAxes: {
- 0: {format: '###,##%'},
- 1: {format: '#Kb',}
- },
- hAxis: { title: "", format: 'HH:mm'},
- series: {
- 0: { type: "line", targetAxisIndex: 0},
- 1: { type: "line", targetAxisIndex: 0},
- 2: { type: "line", targetAxisIndex: 1},
- 3: { type: "line", targetAxisIndex: 1}
- }
- };
-
- var jsonData = $.ajax({
- type: 'POST',
- url: "/db/slice",
- dataType: "json",
- async: false,
- data: { period: 'day', resources: 'cpu,pmc_per,asb,arb', slice: slice, node: node },
- success: function(ret) {
- var result = [];
- var data = new google.visualization.DataTable();
- data.addColumn('datetime', 'Date');
- data.addColumn('number', 'CPU (%)');
- data.addColumn('number', 'MEM (%)');
- data.addColumn('number', 'Traffic Sent (Kb)');
- data.addColumn('number', 'Traffic Received (Kb)');
- $.each(ret, function() {
- result.push([new Date(this[0]), this[1], this[2], this[3], this[4]]);
- });
- data.addRows(result);
- var chart = new google.visualization.LineChart(document.getElementById('graph'));
- chart.draw(data, options);
- }
- }).responseText;
-
- });
+ $('iframe#slicestat_resource').attr('src','http://plestats.planet-lab.eu/node.php?node='+record.hostname);
+
},
/* INTERNAL FUNCTIONS */
});
/* Plugin registration */
- $.plugin('Slicestat', Slicestat);
+ $.plugin('SliceStat', SliceStat);
// TODO Here use cases for instanciating plugins in different ways like in the pastie.
<div id={{ domid }}>
-<p>Slicestat</p>
-<div id="slicestat_resource"></div>
+<iframe id="slicestat_resource" src=""></iframe>
</div>
def _display (self, request, form):
return render(request, 'contact.html', {
'form': form,
- 'topmenu_items': topmenu_items('Contact Us', request),
+ 'topmenu_items': topmenu_items('Contact', request),
'username': the_user (request)
})
# expose this so we can mention the backend URL on the welcome page
def default_env (self):
+ config=Config()
return {
- 'MANIFOLD_URL':Config.manifold_url(),
+ 'MANIFOLD_URL':config.manifold_url(),
}
def post (self,request):
def get (self, request, state=None):
env = self.default_env()
env['username']=the_user(request)
- env['topmenu_items'] = topmenu_items('', request)
+ env['topmenu_items'] = topmenu_items(None, request)
if state: env['state'] = state
elif not env['username']: env['state'] = "Please sign in"
return render_to_response('home-view.html',env, context_instance=RequestContext(request))
from plugins.googlemap import GoogleMap
from plugins.hazelnut import Hazelnut
from plugins.lists.simplelist import SimpleList
-from plugins.slicestat import Slicestat
+from plugins.slicestat import SliceStat
# View for 1 platform and its details
class ResourceView(TemplateView):
def get_context_data(self, **kwargs):
page = Page(self.request)
+
+ page.add_js_files ( [ "js/common.functions.js" ] )
for key, value in kwargs.iteritems():
print "%s = %s" % (key, value)
# query = resource_query,
# )
- resource_stats = Slicestat(
+ resource_stats = SliceStat(
title = None,
page = page,
+ stats = 'node',
key = 'hrn',
query = resource_query
)
# more general variables expected in the template
context['title'] = 'Information about a resource'
# the menu items on the top
- context['topmenu_items'] = topmenu_items('Dashboard', self.request)
+ context['topmenu_items'] = topmenu_items(None, self.request)
# so we can sho who is logged
context['username'] = the_user(self.request)
tmp_default_slice='ple.upmc.myslicedemo'
# temporary : turn off the users part to speed things up
-do_query_users=True
+#do_query_users=True
+do_query_users=False
class SliceView (LoginRequiredAutoLogoutView):
page.add_js_files ( [ "js/common.functions.js" ] )
page.add_js_chunks ('$(function() { messages.debug("sliceview: jQuery version " + $.fn.jquery); });')
page.add_js_chunks ('$(function() { messages.debug("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
- page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(Config.manifold_url()))
+ config=Config()
+ page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(config.manifold_url()))
page.expose_js_metadata()
metadata = page.get_metadata()
# --------------------------------------------------------------------------
# USERS
- if do_query_users:
- tab_users = Tabs(
- page = page,
- domid = 'users',
- outline_complete = True,
- togglable = True,
- title = 'Users',
- active_domid = 'users-list',
- )
- main_stack.insert(tab_users)
-
- tab_users.insert(Hazelnut(
- page = page,
- title = 'Users List',
- domid = 'users-list',
- # tab's sons preferably turn this off
- togglable = False,
- # this is the query at the core of the slice list
- query = sq_user,
- query_all = query_user_all,
- checkboxes = True,
- datatables_options = {
- 'iDisplayLength' : 25,
- 'bLengthChange' : True,
- 'bAutoWidth' : True,
- },
- ))
+# if do_query_users:
+# tab_users = Tabs(
+# page = page,
+# domid = 'users',
+# outline_complete = True,
+# togglable = True,
+# title = 'Users',
+# active_domid = 'users-list',
+# )
+# main_stack.insert(tab_users)
+#
+# tab_users.insert(Hazelnut(
+# page = page,
+# title = 'Users List',
+# domid = 'users-list',
+# # tab's sons preferably turn this off
+# togglable = False,
+# # this is the query at the core of the slice list
+# query = sq_user,
+# query_all = query_user_all,
+# checkboxes = True,
+# datatables_options = {
+# 'iDisplayLength' : 25,
+# 'bLengthChange' : True,
+# 'bAutoWidth' : True,
+# },
+# ))
# DEMO
# --------------------------------------------------------------------------
# MEASUREMENTS
<div class="col-xs-4"> {{ field.errors }} {{ field }} <p class="form-hint">{{ field.help_text }}</p> </div>
</div>
{% endfor %}
- <div class="col-xs-offset-4 col-xs-4">
- <button class="submit btn btn-default" type="submit">Submit</button>
- </div>
+ <button class="submit btn btn-default col-md-offset-4 col-xs-4" type="submit">Send to Support</button>
</fieldset>
</form>
</div>
<div class="col-xs-4"><p class="form-hint">Account Delegation: Manual (Advanced Users)</p></div>
</div>
<div class="form-group" id="register">
- <div class="col-xs-offset-4 col-xs-4">
- <button class="submit btn btn-default" type="submit">Register</button>
- </div>
+ <button class="submit btn btn-default col-md-offset-4 col-xs-4" type="submit">Register</button>
+ </div>
</div>
</fieldset>
</form>
<h1>Resource</h1>
{{resource}}
-{{resource_stats}}
{{resource_as_map}}
+{{resource_stats}}
{% endblock %}
<div class="col-xs-4"> <p class="form-hint">{{ field.help_text }}</p> </div>
</div>
{% endfor %}
- <div class="col-xs-offset-4 col-xs-4">
- <button class="submit btn btn-default" type="submit">Submit</button>
- </div>
+ <button class="submit btn btn-default col-md-offset-4 col-xs-4" type="submit">Request Slice</button>
</fieldset>
</form>
</div>
( 'static/img', glob ('static/img/*')),
( 'static/fonts', glob ('static/fonts/*')),
( 'templates', glob ('templates/*')),
- ( 'apache', [ 'apache/myslice.conf', 'apache/myslice.wsgi' ]),
+ ( 'apache', [ 'apache/myslice.conf' ]),
])
<ul class="dropdown-menu">
{% for dd in d.contents %}
{% if dd.is_active %}<li class='active'>{% else %}<li class='other'>{% endif %}
- <a class="dropdown-toggle" href="{{ dd.href }}"> {{ dd.label }} </a> </li>
+ <a href="{{ dd.href }}"> {{ dd.label }} </a> </li>
{% endfor %}
</ul>
</li>
# ### a dropdown
# { 'label': ..., 'href'=..., 'dropdown':True, 'contents': [ { 'label':.., 'href'} ] }
# , ..]
+
+# current: the beginning of the label in the menu that you want to outline
def topmenu_items (current,request=None):
has_user=request.user.is_authenticated()
result=[]
if has_user:
result.append({'label':'Dashboard', 'href': '/portal/dashboard/'})
result.append({'label':'Request a slice', 'href': '/portal/slice_request/'})
- result.append({'label':'My Account', 'href': '/portal/account/'})
- result.append({'label':'Contact Support', 'href': '/portal/contact/'})
-# Not really useful at this point, is it ?
-# This should probably go into dashboard at some point
-# result.append({'label':'Platforms', 'href': '/portal/platforms/'})
-# the code for building a dropdown instead - but somehow this is broken
-# dropdown = [ {'label':'..', 'href': '..'}, ...]
-# result.append({'label': 'More', 'href':"#", 'dropdown':True, 'contents':dropdown})
+ dropdown = []
+ dropdown.append({'label':'My Account', 'href': '/portal/account/'})
+ dropdown.append({'label':'Contact Support', 'href': '/portal/contact/'})
+ result.append({'label': 'More', 'href':"#", 'dropdown':True, 'contents':dropdown})
else:
result.append({'label':'Home', 'href': '/login'})
# looks like this is accessible to non-logged users
result.append({'label':'Platforms', 'href': '/portal/platforms/'})
result.append({'label':'Register', 'href': '/portal/register/'})
result.append({'label':'Contact Support', 'href': '/portal/contact/'})
- # mark active
- for d in result:
- if 'dropdown' in d:
- for dd in d['contents']:
- if dd['label'] == current: dd['is_active']=True
- else:
- if d['label'] == current: d['is_active']=True
+ # mark active if the provided 'current', even if shorter, matches the beginning of d['label']
+
+ if current is not None:
+ current=current.lower()
+ curlen=len(current)
+ def mark_active(d):
+ if d['label'][:curlen].lower() == current: d['is_active']=True
+ for d in result:
+ mark_active(d)
+ if 'dropdown' in d:
+ for dd in d['contents']: mark_active(dd)
return result
def the_user (request):
except ManifoldException, manifold_result:
# xxx we need a means to display this message to user...
from django.contrib.auth import logout
- logout(request)
+ # in some unusual cases, this might fail
+ try: logout(request)
+ except: pass
return HttpResponseRedirect ('/')
except Exception, e:
# xxx we need to sugarcoat this error message in some error template...
self._queue=[]
# global prelude object
self.prelude=Prelude(css_files='css/plugin.css')
+ self.prelude=Prelude(css_files='css/onelab_marko.css')
# record known plugins hashed on their domid
def record_plugin (self, plugin):
self.add_js_chunks("var MANIFOLD_METADATA =" + self.get_metadata().to_json() + ";")
def expose_js_manifold_config (self):
- self.add_js_chunks(Config.manifold_js_export())
+ config=Config()
+ self.add_js_chunks(config.manifold_js_export())
#################### requirements/prelude management
# just forward to self.prelude - see decorator above
--- /dev/null
+/* @override
+ http://test.myslice.info/static/css/plugin.css
+*/
+
+
+
+/*-------------------------------- MARKO'S STYLES -----*/
+
+
+/* GENERAL */
+
+.container {
+ padding: 0 !important;
+ color: #fff;
+}
+
+.container h1 {
+ color: #fff !important;
+ font-family: Ubuntu;
+ margin-top: 60px;
+}
+
+div.plugin-outline-complete,
+div.plugin-outline-body {
+ border: 0px solid;
+ border-radius: 0;
+ border-color: #ccc;
+ -webkit-transition: padding 200ms ease-out;
+ -moz-transition: padding 200ms ease-out;
+ -o-transition: padding 200ms ease-out;
+ transition: padding 0.2s ease-out;
+ padding: 20px;
+ margin: 0;
+}
+/*
+div.plugin-outline-complete:hover,
+div.plugin-outline-body:hover {
+ padding: 80px 80px 120px 80px;
+}
+*/
+a.plugin-tooltip {
+ font-size: 130%;
+ font-style: normal;
+ font-weight: bold;
+ padding: 5px;
+ color: #333;
+ font-family: Ubuntu, Arial, sans-serif;
+ text-transform: uppercase;
+}
+
+a.plugin-tooltip:hover {
+ color: #fff;
+ text-decoration: none;
+}
+
+
+
+/* LIST VIEW */
+
+h2.well.well-lg {
+ border-radius:0;
+ border: 0;
+ font-family: Ubuntu, arial, sans-serif;
+ text-transform: ;
+ font-weight: normal;
+ font-size: 40px;
+ /* color: #30196d; */
+ color: white;
+ margin-bottom: 0px;
+ margin-top: 0;
+ padding: 30px;
+ opacity: 1;
+ text-align: center;
+ background-color: #30196d;
+}
+
+#complete-resources {
+/* background-color: #92f79e !important; */
+ background-color: #B8B2FF !important;
+}
+
+#complete-filters {
+/* background-color: #4af25d; */
+ background-color: #add7ff;
+}
+
+#complete-users {
+/* background-color: #ff7394 !important; */
+ background-color: #add7ff !important;
+}
+
+#complete-measurements {
+ background-color: !important;
+}
+
+#complete-pending {
+/* background-color: #add7ff !important; */
+ background-color: #B8B2FF !important;
+
+}
+
+#complete-customize-resources {
+ background-color: #efdfdf;
+}
+
+#complete-msgs-pre {
+ background-color: #ccc;
+}
+
+#complete-resources,
+#complete-filters,
+#complete-users,
+#complete-measurements,
+#complete-pending,
+#complete-customize-resources,
+#complete-msgs-pre {
+ opacity: 1;
+ text-align: center;
+ color: #333;
+}
+
+#complete-resources:hover,
+#complete-filters:hover,
+#complete-users:hover,
+#complete-measurements:hover,
+#complete-pending:hover,
+#complete-customize-resources:hover,
+#complete-msgs-pre:hover {
+ opacity: 1;
+}
+
+.nav.nav-tabs {
+ font-family: Ubuntu, Arial, sans-serif;
+ border: 0 !important;
+ border-bottom: 3px solid #fff !important;
+ margin-bottom: 40px;
+}
+
+.nav.nav-tabs li.active a {
+ color: #572bc9;
+ border-left: 0px solid #572bc9;
+ border-top: 0px solid #572bc9;
+ border-right: 0px solid #572bc9;
+}
+
+.nav.nav-tabs li a {
+ color: #333;
+ border: 0 !important;
+ margin-right: 5px;
+}
+
+.nav.nav-tabs li a:hover {
+ color: #333;
+ background: #572bc9;
+ color: #fff;
+ border: 0 !important;
+}
+
+
+
+
+
+/* TOPMENU.CSS */
+
+body {
+ background: #30196d !important;
+ padding-top: 60px;
+ padding-bottom: 0px;
+}
+
+div.topmenu {
+ padding-top: 0px;
+ font-family: Ubuntu, Arial, sans-serif;
+ font-weight: bold;
+ text-transform: ;
+ background: #fff;
+ -webkit-box-shadow: 0px 10px 10px rgba(50, 50, 50, 0.44);
+ -moz-box-shadow: 0px 10px 10px rgba(50, 50, 50, 0.44);
+ box-shadow: 0px 10px 10px rgba(50, 50, 50, 0.44);
+}
+
+.navbar-nav li a,
+.navbar-nav li.other a {
+ padding-top: 25px;
+ padding-bottom: 20px;
+}
+
+.navbar-nav li a:hover {
+ color: #572bc9 !important;
+}
+
+.navbar-nav li.active a {
+.navbar-nav li.active a {
+ background: #eee !important;
+}
+
+ul.logged-in {
+ padding-top: 25px;
+}
+button.logged-in {
+ font-size: 1em;
+ font-weight: bold;
+ margin-left: 5px;
+ margin-top: -5px;
+ background: #572bc9;
+ border: 2px solid #572bc9;
+ color: #eee;
+ padding: 5px 15px;
+ border-radius:5px;
+}
+
+button.logged-in:hover {
+ background: #4af25d;
+ border: 2px solid #4af25d;
+ color: #333;
+}
+li.username {
+ margin-bottom: 10px;
+ font-size: 0.8em;
+ text-transform: none;
+ font-weight: normal;
+ color: #999;
+}
+
+
+/* BOOTSTRAP */
+
+
+ul.pagination li a {
+ background: ;
+ color: #572bc9;
+ font-family: Ubuntu, Arial, sans-serif;
+}
+
+ul.pagination li.active a {
+ background: #572bc9;
+ border: 1px solid #572bc9;
+}
+
+.btn.btn-default {
+ background: #572bc9;
+ color: #ccc;
+ font-family: Ubuntu, Arial, sans-serif;
+ font-weight: bold;
+ border: 0px;
+}
+
+.btn.btn-default:hover {
+ background: #4af25d;
+ color: #333;
+ font-family: Ubuntu, Arial, sans-serif;
+ font-weight: bold;
+ border: 0px;
+}
+
+input {
+ border-radius: 3px;
+ border: none;
+ border: 1px solid #ccc;
+}
+
+
+div.dataTables_length label,
+div.dataTables_filter label,
+div.dataTables_info {
+ font-family: Ubuntu, Arial, sans-serif !important;
+}
+
+
+
+
+/* HAZELNUT */
+
+div.Hazelnut table.dataTable th {
+ font: bold 12px/22px Ubuntu, Arial, sans-serif;
+ color: #333 !important;
+ border-right: 0px solid #333 !important;
+ border-bottom: 0px solid #C1DAD7 !important;
+ border-top: 0px solid #C1DAD7 !important;
+ letter-spacing: 1px;
+ text-transform: uppercase;
+ text-align: left;
+ padding: 8px 12px 4px 20px;
+ vertical-align:middle;
+ background: # url(../img/tablesort-header.jpg) no-repeat !important;
+}
+
+div.Hazelnut table.dataTable td, div.Hazelnut table.dataTable textarea, div.Hazelnut table.dataTable input [type="text"] {
+ font: normal 12px Ubuntu, Arial, Helvetica, sans-serif;
+ border-right: 0px solid #fff !important;
+ border-bottom: 1px solid #fff !important;
+}
+
+div.Hazelnut table.dataTable thead {
+ background: url('../img/tablesort-header.png') repeat-x !important;
+ background-color: #caebea;
+}
+
+div.Hazelnut table.dataTable tfoot {
+ background: url('../img/tablesort-header.png') repeat-x !important;
+ background-color: # !important;
+}
+
+
+/* QUERY EDITOR */
+
+table.query-editor {
+ margin: 40px auto !important;
+ clear: both;
+ /* width: 80%;*/
+ width: 100% !important;
+ font-family: Ubuntu;
+}
+
+.query-editor-spacer,
+.plugin.ResourcesSelected,
+.plugin.Tabs {
+ margin-top: 60px !important;
+}
+
+table.query-editor td {
+ padding: 5px 5px !important;
+ font: normal 12px Ubuntu, Arial, sans-serif !important;
+}
+
+
+
+/* DASHBOARD */
+
+#ms-dashboard-profile,
+#ms-dashboard-testbeds,
+#ms-dashboard-slices {
+ -webkit-transition: all 50ms ease-out;
+ -moz-transition: all 50ms ease-out;
+ -o-transition: all 50ms ease-out;
+ transition: all 0.05s ease-out;
+ padding-top: 140px;
+ padding-bottom: 60px;
+ margin-top: 60px;
+ color: #fff;
+ font-family: Ubuntu, Arial, sans-serif;
+ text-align: center;
+
+}
+
+#ms-dashboard-profile:hover,
+#ms-dashboard-testbeds:hover,
+#ms-dashboard-slices:hover {
+ margin-top: 65px;
+}
+
+#ms-dashboard-profile {
+ background: url("../img/icon_users_color.png") top center no-repeat;
+
+}
+
+#ms-dashboard-testbeds {
+ background: url("../img/icon_testbed_color.png") top center no-repeat;
+}
+
+#ms-dashboard-slices {
+ background: url("../img/icon_slices_color.png") top center no-repeat;
+}
+
+.ms-dashboard-content ul {
+ list-style-type: none !important;
+ padding-left: 0;
+ text-align: center !important;
+}
+
+.ms-dashboard-content {
+ padding: 0 !important;
+}
+
+.ms-dashboard-content a {
+ color: /*#572bc9*/ #ff7394 !important;
+}
+
+.ms-dashboard-caption h2 {
+ font-family: Ubuntu, Arial, sans-serif;
+ border-bottom: 0 !important;
+ text-transform: uppercase;
+}
+
+#ms-dashboard-profile>div.ms-dashboard-caption {
+ background: no-repeat url(#) !important;
+ padding-left: 0 !important;
+}
+
+#ms-dashboard-testbeds>div.ms-dashboard-caption {
+ background: no-repeat url(#) !important;
+ padding-left: 0 !important;
+}
+
+#ms-dashboard-slices>div.ms-dashboard-caption {
+ background: no-repeat url(#) !important;
+ padding-left: 0 !important;
+}
+
+.simplelist {
+ font-size: 100%;
+ text-align: center !important;
+ margin: 0 auto;
+}
+
+
+
+
+
+