Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
itminedu
synnefo
Commits
aa532ec9
Commit
aa532ec9
authored
Oct 30, 2012
by
Christos Stavrakakis
Browse files
Merge branch 'ui-0.11' into devel-0.12
parents
dd9af521
95cbdb84
Changes
64
Expand all
Hide whitespace changes
Inline
Side-by-side
snf-common/Changelog
View file @
aa532ec9
...
...
@@ -6,6 +6,7 @@ dev
***
* AMQP client which supports connection with multiple brokers using
HA-queues and publisher-confirms to guarantee delivery of messages.
* Added astakos client lib helper get_token_from_cookie
v0.9.7
------
...
...
snf-common/synnefo/lib/astakos.py
View file @
aa532ec9
# Copyright 2011-2012 GRNET S.A. All rights reserved.
#
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
...
...
@@ -25,7 +25,7 @@
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
...
...
@@ -69,13 +69,13 @@ def authenticate(token, authentication_url='http://127.0.0.1:8000/im/authenticat
def
user_for_token
(
token
,
authentication_url
,
override_users
):
if
not
token
:
return
None
if
override_users
:
try
:
return
{
'uniq'
:
override_users
[
token
].
decode
(
'utf8'
)}
except
:
return
None
try
:
return
authenticate
(
token
,
authentication_url
)
except
Exception
,
e
:
...
...
@@ -87,7 +87,7 @@ def user_for_token(token, authentication_url, override_users):
def
get_user
(
request
,
authentication_url
=
'http://127.0.0.1:8000/im/authenticate'
,
override_users
=
{},
fallback_token
=
None
):
request
.
user
=
None
request
.
user_uniq
=
None
# Try to find token in a parameter or in a request header.
user
=
user_for_token
(
request
.
GET
.
get
(
'X-Auth-Token'
),
authentication_url
,
override_users
)
if
not
user
:
...
...
@@ -96,6 +96,22 @@ def get_user(request, authentication_url='http://127.0.0.1:8000/im/authenticate'
user
=
user_for_token
(
fallback_token
,
authentication_url
,
override_users
)
if
not
user
:
return
request
.
user
=
user
request
.
user_uniq
=
user
[
'uniq'
]
def
get_token_from_cookie
(
request
,
cookiename
):
"""
Extract token from the cookie name provided. Cookie should be in the same
form as astakos service sets its cookie contents::
<user_uniq>|<user_token>
"""
try
:
cookie_content
=
unquote
(
request
.
COOKIES
.
get
(
cookiename
,
None
))
return
cookie_content
.
split
(
"|"
)[
1
]
except
AttributeError
:
pass
return
None
snf-common/synnefo/settings/__init__.py
View file @
aa532ec9
...
...
@@ -65,6 +65,6 @@ if os.path.exists(SYNNEFO_SETTINGS_DIR):
try
:
execfile
(
os
.
path
.
abspath
(
f
))
except
Exception
as
e
:
print
>>
sys
.
stderr
,
"Failed to read settings file: %s [%
s
]"
%
\
print
>>
sys
.
stderr
,
"Failed to read settings file: %s [%
r
]"
%
\
(
os
.
path
.
abspath
(
f
),
e
)
raise
SystemExit
(
1
)
snf-cyclades-app/Changelog
View file @
aa532ec9
Changelog
---------
v0.12.0
*******
FIXES:
UI:
* Fix unclosed DIV's and other minor html fixes.
*
NEW FEATURES:
UI:
* Optionally group public network interfaces in one network view in ui
Configurable by the UI_GROUP_PUBLIC_NETWORKS setting (defaults to True).
* New setting UI_CHANGES_SINCE_ALIGMENT to allow aligment of the date used
by ui in api calls that support changes-since parameter.
v0.11.0
*******
...
...
snf-cyclades-app/synnefo/admin/templates/base.html
View file @
aa532ec9
...
...
@@ -9,7 +9,7 @@
<script
src=
"/admin/static/main.js"
></script>
{% block head %}{% endblock %}
</head>
<body>
<body
data-spy=
"scroll"
data-target=
".subnav"
data-offset=
"50"
>
<div
class=
"container"
>
<div
style=
"padding: 5px 0px 20px 0px"
>
<img
src=
"/admin/static/banner.png"
width=
"776"
height=
"82"
>
...
...
snf-cyclades-app/synnefo/api/servers.py
View file @
aa532ec9
...
...
@@ -64,6 +64,7 @@ urlpatterns = patterns('synnefo.api.servers',
(
r
'^/(\d+)/meta(?:.json|.xml)?$'
,
'metadata_demux'
),
(
r
'^/(\d+)/meta/(.+?)(?:.json|.xml)?$'
,
'metadata_item_demux'
),
(
r
'^/(\d+)/stats(?:.json|.xml)?$'
,
'server_stats'
),
(
r
'^/(\d+)/diagnostics(?:.json)?$'
,
'get_server_diagnostics'
),
)
...
...
@@ -138,9 +139,43 @@ def vm_to_dict(vm, detail=False):
attachments
=
[
nic_to_dict
(
nic
)
for
nic
in
vm
.
nics
.
all
()]
if
attachments
:
d
[
'attachments'
]
=
{
'values'
:
attachments
}
# include the latest vm diagnostic, if set
diagnostic
=
vm
.
get_last_diagnostic
()
if
diagnostic
:
d
[
'diagnostics'
]
=
diagnostics_to_dict
([
diagnostic
])
return
d
def
diagnostics_to_dict
(
diagnostics
):
"""
Extract api data from diagnostics QuerySet.
"""
entries
=
list
()
for
diagnostic
in
diagnostics
:
# format source date if set
formatted_source_date
=
None
if
diagnostic
.
source_date
:
formatted_source_date
=
util
.
isoformat
(
diagnostic
.
source_date
)
entry
=
{
'source'
:
diagnostic
.
source
,
'created'
:
util
.
isoformat
(
diagnostic
.
created
),
'message'
:
diagnostic
.
message
,
'details'
:
diagnostic
.
details
,
'level'
:
diagnostic
.
level
,
}
if
formatted_source_date
:
entry
[
'source_date'
]
=
formatted_source_date
entries
.
append
(
entry
)
return
entries
def
render_server
(
request
,
server
,
status
=
200
):
if
request
.
serialization
==
'xml'
:
data
=
render_to_string
(
'server.xml'
,
{
...
...
@@ -151,6 +186,24 @@ def render_server(request, server, status=200):
return
HttpResponse
(
data
,
status
=
status
)
def
render_diagnostics
(
request
,
diagnostics_dict
,
status
=
200
):
"""
Render diagnostics dictionary to json response.
"""
return
HttpResponse
(
json
.
dumps
(
diagnostics_dict
),
status
=
status
)
@
util
.
api_method
(
'GET'
)
def
get_server_diagnostics
(
request
,
server_id
):
"""
Virtual machine diagnostics api view.
"""
log
.
debug
(
'server_diagnostics %s'
,
server_id
)
vm
=
util
.
get_vm
(
server_id
,
request
.
user_uniq
)
diagnostics
=
diagnostics_to_dict
(
vm
.
diagnostics
.
all
())
return
render_diagnostics
(
request
,
diagnostics
)
@
util
.
api_method
(
'GET'
)
def
list_servers
(
request
,
detail
=
False
):
# Normal Response Codes: 200, 203
...
...
@@ -164,6 +217,7 @@ def list_servers(request, detail=False):
user_vms
=
VirtualMachine
.
objects
.
filter
(
userid
=
request
.
user_uniq
)
since
=
util
.
isoparse
(
request
.
GET
.
get
(
'changes-since'
))
if
since
:
user_vms
=
user_vms
.
filter
(
updated__gte
=
since
)
if
not
user_vms
:
...
...
snf-cyclades-app/synnefo/app_settings/__init__.py
View file @
aa532ec9
...
...
@@ -5,7 +5,9 @@ synnefo_web_apps = [
'synnefo.db'
,
'synnefo.logic'
,
'synnefo.plankton'
,
'synnefo.helpdesk'
,
'synnefo.ui.userdata'
,
'synnefo.helpdesk'
,
]
synnefo_web_middleware
=
[]
...
...
@@ -14,4 +16,5 @@ synnefo_web_context_processors = ['synnefo.lib.context_processors.cloudbar']
synnefo_static_files
=
{
'synnefo.ui'
:
'ui/static'
,
'synnefo.admin'
:
'admin'
,
'synnefo.helpdesk'
:
'helpdesk'
,
}
snf-cyclades-app/synnefo/app_settings/default/helpdesk.py
0 → 100644
View file @
aa532ec9
#Enable the helpdesk application
#HELPDESK_ENABLED = True
# Which is the cookie name that stores the token, leave it commented out
# to use same value as UI_AUTH_COOKIE_NAME value.
#HELPDESK_AUTH_COOKIE_NAME = UI_AUTH_COOKIE_NAME
snf-cyclades-app/synnefo/app_settings/default/ui.py
View file @
aa532ec9
...
...
@@ -35,6 +35,10 @@ UI_UPDATE_INTERVAL_MAX = UI_UPDATE_INTERVAL * 3
# Fast update interval
UI_UPDATE_INTERVAL_FAST
=
UI_UPDATE_INTERVAL
/
2
# Miliseconds to remove from the previous server response time used in
# consecutive API calls (aligning changes-since attribute).
UI_CHANGES_SINCE_ALIGNMENT
=
0
# List of emails used for sending the feedback messages to (following the ADMINS format)
FEEDBACK_CONTACTS
=
(
# ('Contact Name', 'contact_email@domain.com'),
...
...
@@ -79,7 +83,7 @@ VM_CREATE_SUGGESTED_FLAVORS = {
# A list of metadata keys to clone from image
# to the virtual machine on its creation.
VM_IMAGE_COMMON_METADATA
=
[
"OS"
,
"loginname"
,
"logindomain"
]
VM_IMAGE_COMMON_METADATA
=
[
"OS"
,
"loginname"
,
"logindomain"
,
"users"
,
"remote"
]
# A list of suggested vm roles to display to user on create wizard
VM_CREATE_SUGGESTED_ROLES
=
[
"Database server"
,
"File server"
,
"Mail server"
,
"Web server"
,
"Proxy"
]
...
...
@@ -143,7 +147,7 @@ UI_NETWORK_ALLOW_DUPLICATE_VM_NICS = False
# Whether to display destroy action on private networks that contain vms. If
# set to True, destroy action will only get displayed if user disconnect all
# virtual machines from the network.
UI_NETWORK_STRICT_DESTROY
=
Fals
e
UI_NETWORK_STRICT_DESTROY
=
Tru
e
###############
...
...
snf-cyclades-app/synnefo/app_settings/urls.py
View file @
aa532ec9
...
...
@@ -41,5 +41,6 @@ urlpatterns = patterns('',
name
=
'ui_machines_connect'
),
(
r
'^api/'
,
include
(
'synnefo.api.urls'
)),
(
r
'^plankton/'
,
include
(
'synnefo.plankton.urls'
)),
(
r
'^helpdesk/'
,
include
(
'synnefo.helpdesk.urls'
)),
)
snf-cyclades-app/synnefo/db/migrations/0057_auto__add_virtualmachinediagnostic.py
0 → 100644
View file @
aa532ec9
# encoding: utf-8
import
datetime
from
south.db
import
db
from
south.v2
import
SchemaMigration
from
django.db
import
models
class
Migration
(
SchemaMigration
):
def
forwards
(
self
,
orm
):
# Adding model 'VirtualMachineDiagnostic'
db
.
create_table
(
'db_virtualmachinediagnostic'
,
(
(
'id'
,
self
.
gf
(
'django.db.models.fields.AutoField'
)(
primary_key
=
True
)),
(
'created'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
auto_now_add
=
True
,
blank
=
True
)),
(
'machine'
,
self
.
gf
(
'django.db.models.fields.related.ForeignKey'
)(
related_name
=
'diagnostics'
,
to
=
orm
[
'db.VirtualMachine'
])),
(
'level'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
20
)),
(
'source'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
100
)),
(
'source_date'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
null
=
True
)),
(
'message'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
255
)),
(
'details'
,
self
.
gf
(
'django.db.models.fields.TextField'
)(
null
=
True
)),
))
db
.
send_create_signal
(
'db'
,
[
'VirtualMachineDiagnostic'
])
def
backwards
(
self
,
orm
):
# Deleting model 'VirtualMachineDiagnostic'
db
.
delete_table
(
'db_virtualmachinediagnostic'
)
models
=
{
'db.backend'
:
{
'Meta'
:
{
'ordering'
:
"['clustername']"
,
'object_name'
:
'Backend'
},
'clustername'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'128'
}),
'ctotal'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'default'
:
'0'
}),
'dfree'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'default'
:
'0'
}),
'drained'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'dtotal'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'default'
:
'0'
}),
'hash'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'40'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'index'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'default'
:
'0'
,
'unique'
:
'True'
}),
'mfree'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'default'
:
'0'
}),
'mtotal'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'default'
:
'0'
}),
'offline'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'password_hash'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'null'
:
'True'
,
'blank'
:
'True'
}),
'pinst_cnt'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'default'
:
'0'
}),
'port'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'default'
:
'5080'
}),
'updated'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'blank'
:
'True'
}),
'username'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'64'
,
'null'
:
'True'
,
'blank'
:
'True'
})
},
'db.backendnetwork'
:
{
'Meta'
:
{
'unique_together'
:
"(('network', 'backend'),)"
,
'object_name'
:
'BackendNetwork'
},
'backend'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'networks'"
,
'to'
:
"orm['db.Backend']"
}),
'backendjobid'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'null'
:
'True'
}),
'backendjobstatus'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'null'
:
'True'
}),
'backendlogmsg'
:
(
'django.db.models.fields.TextField'
,
[],
{
'null'
:
'True'
}),
'backendopcode'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'null'
:
'True'
}),
'backendtime'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime(1, 1, 1, 0, 0)'
}),
'created'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'blank'
:
'True'
}),
'deleted'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'mac_prefix'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
}),
'network'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'backend_networks'"
,
'to'
:
"orm['db.Network']"
}),
'operstate'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'PENDING'"
,
'max_length'
:
'30'
}),
'updated'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now'
:
'True'
,
'blank'
:
'True'
})
},
'db.bridgepooltable'
:
{
'Meta'
:
{
'object_name'
:
'BridgePoolTable'
},
'available_map'
:
(
'django.db.models.fields.TextField'
,
[],
{
'default'
:
"''"
}),
'base'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
,
'null'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'offset'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'null'
:
'True'
}),
'reserved_map'
:
(
'django.db.models.fields.TextField'
,
[],
{
'default'
:
"''"
}),
'size'
:
(
'django.db.models.fields.IntegerField'
,
[],
{})
},
'db.flavor'
:
{
'Meta'
:
{
'unique_together'
:
"(('cpu', 'ram', 'disk', 'disk_template'),)"
,
'object_name'
:
'Flavor'
},
'cpu'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'default'
:
'0'
}),
'deleted'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'disk'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'default'
:
'0'
}),
'disk_template'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'drbd'"
,
'max_length'
:
'32'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'ram'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'default'
:
'0'
})
},
'db.ippooltable'
:
{
'Meta'
:
{
'object_name'
:
'IPPoolTable'
},
'available_map'
:
(
'django.db.models.fields.TextField'
,
[],
{
'default'
:
"''"
}),
'base'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
,
'null'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'offset'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'null'
:
'True'
}),
'reserved_map'
:
(
'django.db.models.fields.TextField'
,
[],
{
'default'
:
"''"
}),
'size'
:
(
'django.db.models.fields.IntegerField'
,
[],
{})
},
'db.macprefixpooltable'
:
{
'Meta'
:
{
'object_name'
:
'MacPrefixPoolTable'
},
'available_map'
:
(
'django.db.models.fields.TextField'
,
[],
{
'default'
:
"''"
}),
'base'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
,
'null'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'offset'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'null'
:
'True'
}),
'reserved_map'
:
(
'django.db.models.fields.TextField'
,
[],
{
'default'
:
"''"
}),
'size'
:
(
'django.db.models.fields.IntegerField'
,
[],
{})
},
'db.network'
:
{
'Meta'
:
{
'object_name'
:
'Network'
},
'action'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
'None'
,
'max_length'
:
'32'
,
'null'
:
'True'
}),
'created'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'blank'
:
'True'
}),
'deleted'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'dhcp'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'True'
}),
'gateway'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
,
'null'
:
'True'
}),
'gateway6'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'64'
,
'null'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'link'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'null'
:
'True'
}),
'mac_prefix'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
}),
'machines'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['db.VirtualMachine']"
,
'through'
:
"orm['db.NetworkInterface']"
,
'symmetrical'
:
'False'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
}),
'pool'
:
(
'django.db.models.fields.related.OneToOneField'
,
[],
{
'related_name'
:
"'network'"
,
'unique'
:
'True'
,
'null'
:
'True'
,
'to'
:
"orm['db.IPPoolTable']"
}),
'public'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'state'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'PENDING'"
,
'max_length'
:
'32'
}),
'subnet'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'10.0.0.0/24'"
,
'max_length'
:
'32'
}),
'subnet6'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'64'
,
'null'
:
'True'
}),
'type'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'PRIVATE_PHYSICAL_VLAN'"
,
'max_length'
:
'50'
}),
'updated'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now'
:
'True'
,
'blank'
:
'True'
}),
'userid'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'null'
:
'True'
})
},
'db.networkinterface'
:
{
'Meta'
:
{
'object_name'
:
'NetworkInterface'
},
'created'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'blank'
:
'True'
}),
'dirty'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'firewall_profile'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'null'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'index'
:
(
'django.db.models.fields.IntegerField'
,
[],
{}),
'ipv4'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'15'
,
'null'
:
'True'
}),
'ipv6'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
,
'null'
:
'True'
}),
'mac'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'32'
}),
'machine'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'nics'"
,
'to'
:
"orm['db.VirtualMachine']"
}),
'network'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'nics'"
,
'to'
:
"orm['db.Network']"
}),
'updated'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now'
:
'True'
,
'blank'
:
'True'
})
},
'db.virtualmachine'
:
{
'Meta'
:
{
'object_name'
:
'VirtualMachine'
},
'action'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'null'
:
'True'
}),
'backend'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'virtual_machines'"
,
'null'
:
'True'
,
'to'
:
"orm['db.Backend']"
}),
'backend_hash'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'null'
:
'True'
}),
'backendjobid'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'null'
:
'True'
}),
'backendjobstatus'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'null'
:
'True'
}),
'backendlogmsg'
:
(
'django.db.models.fields.TextField'
,
[],
{
'null'
:
'True'
}),
'backendopcode'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'null'
:
'True'
}),
'backendtime'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime(1, 1, 1, 0, 0)'
}),
'buildpercentage'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'default'
:
'0'
}),
'created'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'blank'
:
'True'
}),
'deleted'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'flavor'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['db.Flavor']"
}),
'hostid'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'imageid'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
}),
'operstate'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'null'
:
'True'
}),
'suspended'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'updated'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now'
:
'True'
,
'blank'
:
'True'
}),
'userid'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
})
},
'db.virtualmachinediagnostic'
:
{
'Meta'
:
{
'ordering'
:
"['-created']"
,
'object_name'
:
'VirtualMachineDiagnostic'
},
'created'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'blank'
:
'True'
}),
'details'
:
(
'django.db.models.fields.TextField'
,
[],
{
'null'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'level'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'20'
}),
'machine'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'diagnostics'"
,
'to'
:
"orm['db.VirtualMachine']"
}),
'message'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
}),
'source'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'source_date'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'null'
:
'True'
})
},
'db.virtualmachinemetadata'
:
{
'Meta'
:
{
'unique_together'
:
"(('meta_key', 'vm'),)"
,
'object_name'
:
'VirtualMachineMetadata'
},
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'meta_key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
}),
'meta_value'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'500'
}),
'vm'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'metadata'"
,
'to'
:
"orm['db.VirtualMachine']"
})
}
}
complete_apps
=
[
'db'
]
snf-cyclades-app/synnefo/db/models.py
View file @
aa532ec9
...
...
@@ -295,6 +295,12 @@ class VirtualMachine(models.Model):
else
:
raise
ServiceUnavailable
def
get_last_diagnostic
(
self
,
**
filters
):
try
:
return
self
.
diagnostics
.
filter
()[
0
]
except
IndexError
:
return
None
@
staticmethod
def
put_client
(
client
):
put_rapi_client
(
client
)
...
...
@@ -700,3 +706,55 @@ def pooled_rapi_client(obj):
yield
client
finally
:
put_rapi_client
(
client
)
class
VirtualMachineDiagnosticManager
(
models
.
Manager
):
"""
Custom manager for :class:`VirtualMachineDiagnostic` model.
"""
# diagnostic creation helpers
def
create_for_vm
(
self
,
vm
,
level
,
message
,
**
kwargs
):
attrs
=
{
'machine'
:
vm
,
'level'
:
level
,
'message'
:
message
}
attrs
.
update
(
kwargs
)
# update instance updated time
self
.
create
(
**
attrs
)
vm
.
save
()
def
create_error
(
self
,
vm
,
**
kwargs
):
self
.
create_for_vm
(
vm
,
'ERROR'
,
**
kwargs
)
def
create_debug
(
self
,
vm
,
**
kwargs
):
self
.
create_for_vm
(
vm
,
'DEBUG'
,
**
kwargs
)
def
since
(
self
,
vm
,
created_since
,
**
kwargs
):
return
self
.
get_query_set
().
filter
(
vm
=
vm
,
created__gt
=
created_since
,
**
kwargs
)
class
VirtualMachineDiagnostic
(
models
.
Model
):
"""
Model to store backend information messages that relate to the state of
the virtual machine.
"""
TYPES
=
(
(
'ERROR'
,
'Error'
),
(
'WARNING'
,
'Warning'
),
(
'INFO'
,
'Info'
),
(
'DEBUG'
,
'Debug'
),
)
objects
=
VirtualMachineDiagnosticManager
()
created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
machine
=
models
.
ForeignKey
(
'VirtualMachine'
,
related_name
=
"diagnostics"
)
level
=
models
.
CharField
(
max_length
=
20
,
choices
=
TYPES
)
source
=
models
.
CharField
(
max_length
=
100
)
source_date
=
models
.
DateTimeField
(
null
=
True
)
message
=
models
.
CharField
(
max_length
=
255
)
details
=
models
.
TextField
(
null
=
True
)
class
Meta
:
ordering
=
[
'-created'
]
snf-cyclades-app/synnefo/helpdesk/__init__.py
0 → 100644
View file @
aa532ec9
snf-cyclades-app/synnefo/helpdesk/fixtures/helpdesk_test.json
0 → 100644
View file @
aa532ec9
[
{
"model"
:
"db.VirtualMachine"
,
"pk"
:
1001
,
"fields"
:
{
"userid"
:
"testuser@test.com"
,
"name"
:
"user1 vm"
,
"created"
:
"2011-02-06 00:00:00"
,
"updated"
:
"2011-02-06 00:00:00"
,
"imageid"
:
"1"
,
"hostid"
:
"HAL-9000"
,
"flavor"
:
1
,
"operstate"
:
"STOPPED"
}
},
{
"model"
:
"db.VirtualMachine"
,
"pk"
:
1002
,
"fields"
:
{
"userid"
:
"testuser2@test.com"
,
"name"
:
"user2 vm1"
,
"created"
:
"2011-02-10 00:00:00"
,
"updated"
:
"2011-02-10 00:00:00"
,
"imageid"
:
"1"
,
"hostid"
:
"HAL-9000"
,
"flavor"
:
1
,
"operstate"
:
"BUILD"
}
},
{
"model"
:
"db.VirtualMachine"
,
"pk"
:
1003
,
"fields"
:
{
"userid"
:
"testuser2@test.com"
,
"name"
:
"user2 vm2"
,
"created"
:
"2011-02-10 00:00:00"
,
"updated"
:
"2011-02-10 00:00:00"
,
"imageid"
:
"1"
,
"hostid"
:
"HAL-9000"
,
"flavor"
:
1
,
"operstate"
:
"BUILD"
}
},
{
"model"
:
"db.VirtualMachineMetadata"
,
"pk"
:
1
,
"fields"
:
{
"meta_key"
:
"OS"
,
"meta_value"
:
"debian"
,