Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
94
Merge Requests
10
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
A prog2-höz tartozó friss repo anyagok itt elérhetőek:
https://git.iit.bme.hu/
Commit
5179872f
authored
Nov 12, 2019
by
Bálint Máhonfai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into export_import_disk
parents
7a8c2ac5
7a49024a
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
53 additions
and
27 deletions
+53
-27
circle/dashboard/models.py
+9
-5
circle/dashboard/store_api.py
+17
-10
circle/dashboard/views/store.py
+7
-1
circle/firewall/tasks/local_tasks.py
+9
-3
circle/manager/mancelery.py
+2
-1
circle/storage/models.py
+3
-3
circle/vm/models/node.py
+1
-1
circle/vm/operations.py
+1
-1
circle/vm/tasks/local_periodic_tasks.py
+4
-2
No files found.
circle/dashboard/models.py
View file @
5179872f
...
@@ -162,7 +162,7 @@ class ConnectCommand(Model):
...
@@ -162,7 +162,7 @@ class ConnectCommand(Model):
validators
=
[
connect_command_template_validator
])
validators
=
[
connect_command_template_validator
])
class
Meta
:
class
Meta
:
ordering
=
(
'id'
,
)
ordering
=
(
'id'
,)
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
self
.
template
return
self
.
template
...
@@ -263,7 +263,7 @@ class Profile(Model):
...
@@ -263,7 +263,7 @@ class Profile(Model):
super
(
Profile
,
self
)
.
save
(
*
args
,
**
kwargs
)
super
(
Profile
,
self
)
.
save
(
*
args
,
**
kwargs
)
class
Meta
:
class
Meta
:
ordering
=
(
'id'
,
)
ordering
=
(
'id'
,)
permissions
=
(
permissions
=
(
(
'use_autocomplete'
,
_
(
'Can use autocomplete.'
)),
(
'use_autocomplete'
,
_
(
'Can use autocomplete.'
)),
)
)
...
@@ -275,7 +275,7 @@ class FutureMember(Model):
...
@@ -275,7 +275,7 @@ class FutureMember(Model):
group
=
ForeignKey
(
Group
)
group
=
ForeignKey
(
Group
)
class
Meta
:
class
Meta
:
ordering
=
(
'id'
,
)
ordering
=
(
'id'
,)
unique_together
=
(
'org_id'
,
'group'
)
unique_together
=
(
'org_id'
,
'group'
)
def
__unicode__
(
self
):
def
__unicode__
(
self
):
...
@@ -295,7 +295,7 @@ class GroupProfile(AclBase):
...
@@ -295,7 +295,7 @@ class GroupProfile(AclBase):
description
=
TextField
(
blank
=
True
)
description
=
TextField
(
blank
=
True
)
class
Meta
:
class
Meta
:
ordering
=
(
'id'
,
)
ordering
=
(
'id'
,)
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
self
.
group
.
name
return
self
.
group
.
name
...
@@ -331,7 +331,11 @@ def create_profile(user):
...
@@ -331,7 +331,11 @@ def create_profile(user):
profile
,
created
=
Profile
.
objects
.
get_or_create
(
user
=
user
)
profile
,
created
=
Profile
.
objects
.
get_or_create
(
user
=
user
)
try
:
try
:
Store
(
user
)
.
create_user
(
profile
.
smb_password
,
None
,
profile
.
disk_quota
)
store
=
Store
(
user
)
if
store
.
user_exist
():
profile
.
disk_quota
=
store
.
get_quota
()[
'soft'
]
profile
.
save
()
store
.
create_user
(
profile
.
smb_password
,
None
,
profile
.
disk_quota
)
except
:
except
:
logger
.
exception
(
"Can't create user
%
s"
,
unicode
(
user
))
logger
.
exception
(
"Can't create user
%
s"
,
unicode
(
user
))
return
created
return
created
...
...
circle/dashboard/store_api.py
View file @
5179872f
...
@@ -44,9 +44,19 @@ class NoStoreException(StoreApiException):
...
@@ -44,9 +44,19 @@ class NoStoreException(StoreApiException):
pass
pass
class
NoOrgIdException
(
StoreApiException
):
pass
class
Store
(
object
):
class
Store
(
object
):
def
__init__
(
self
,
user
,
default_timeout
=
0.5
):
def
__init__
(
self
,
user
,
default_timeout
=
0.5
):
self
.
store_url
=
settings
.
STORE_URL
if
not
self
.
store_url
:
raise
NoStoreException
if
not
user
.
profile
.
org_id
:
raise
NoOrgIdException
self
.
username
=
'u-
%
s'
%
user
.
profile
.
org_id
self
.
request_args
=
{
'verify'
:
settings
.
STORE_VERIFY_SSL
}
self
.
request_args
=
{
'verify'
:
settings
.
STORE_VERIFY_SSL
}
if
settings
.
STORE_SSL_AUTH
:
if
settings
.
STORE_SSL_AUTH
:
self
.
request_args
[
'cert'
]
=
(
settings
.
STORE_CLIENT_CERT
,
self
.
request_args
[
'cert'
]
=
(
settings
.
STORE_CLIENT_CERT
,
...
@@ -54,18 +64,15 @@ class Store(object):
...
@@ -54,18 +64,15 @@ class Store(object):
if
settings
.
STORE_BASIC_AUTH
:
if
settings
.
STORE_BASIC_AUTH
:
self
.
request_args
[
'auth'
]
=
(
settings
.
STORE_CLIENT_USER
,
self
.
request_args
[
'auth'
]
=
(
settings
.
STORE_CLIENT_USER
,
settings
.
STORE_CLIENT_PASSWORD
)
settings
.
STORE_CLIENT_PASSWORD
)
self
.
username
=
"u-
%
d"
%
user
.
pk
self
.
default_timeout
=
default_timeout
self
.
default_timeout
=
default_timeout
self
.
store_url
=
settings
.
STORE_URL
if
not
self
.
store_url
:
raise
NoStoreException
def
_request
(
self
,
url
,
method
=
get
,
timeout
=
None
,
def
_request
(
self
,
url
,
method
=
get
,
timeout
=
None
,
raise_status_code
=
True
,
**
kwargs
):
raise_status_code
=
True
,
**
kwargs
):
url
=
urljoin
(
self
.
store_url
,
url
)
url
=
urljoin
(
self
.
store_url
,
url
)
if
timeout
is
None
:
if
timeout
is
None
:
timeout
=
self
.
default_timeout
timeout
=
self
.
default_timeout
payload
=
json
.
dumps
(
kwargs
)
if
kwargs
else
None
kwargs
[
'USER'
]
=
self
.
username
payload
=
json
.
dumps
(
kwargs
)
try
:
try
:
headers
=
{
'content-type'
:
'application/json'
}
headers
=
{
'content-type'
:
'application/json'
}
response
=
method
(
url
,
data
=
payload
,
headers
=
headers
,
response
=
method
(
url
,
data
=
payload
,
headers
=
headers
,
...
@@ -83,7 +90,7 @@ class Store(object):
...
@@ -83,7 +90,7 @@ class Store(object):
return
response
return
response
def
_request_cmd
(
self
,
cmd
,
**
kwargs
):
def
_request_cmd
(
self
,
cmd
,
**
kwargs
):
return
self
.
_request
(
self
.
username
,
post
,
CMD
=
cmd
,
**
kwargs
)
return
self
.
_request
(
"/user/"
,
post
,
CMD
=
cmd
,
**
kwargs
)
def
list
(
self
,
path
,
process
=
True
):
def
list
(
self
,
path
,
process
=
True
):
r
=
self
.
_request_cmd
(
"LIST"
,
PATH
=
path
)
r
=
self
.
_request_cmd
(
"LIST"
,
PATH
=
path
)
...
@@ -119,7 +126,7 @@ class Store(object):
...
@@ -119,7 +126,7 @@ class Store(object):
self
.
_request_cmd
(
"RENAME"
,
PATH
=
old_path
,
NEW_NAME
=
new_name
)
self
.
_request_cmd
(
"RENAME"
,
PATH
=
old_path
,
NEW_NAME
=
new_name
)
def
get_quota
(
self
):
# no CMD? :o
def
get_quota
(
self
):
# no CMD? :o
r
=
self
.
_request
(
self
.
username
)
r
=
self
.
_request
(
"/user/"
)
quota
=
r
.
json
()
quota
=
r
.
json
()
quota
.
update
({
quota
.
update
({
'readable_used'
:
filesizeformat
(
float
(
quota
[
'used'
])),
'readable_used'
:
filesizeformat
(
float
(
quota
[
'used'
])),
...
@@ -129,17 +136,17 @@ class Store(object):
...
@@ -129,17 +136,17 @@ class Store(object):
return
quota
return
quota
def
set_quota
(
self
,
quota
):
def
set_quota
(
self
,
quota
):
self
.
_request
(
"/quota/"
+
self
.
username
,
post
,
QUOTA
=
quota
)
self
.
_request
(
"/quota/"
,
post
,
QUOTA
=
quota
)
def
user_exist
(
self
):
def
user_exist
(
self
):
try
:
try
:
self
.
_request
(
self
.
username
)
self
.
_request
(
"/user/"
)
return
True
return
True
except
NotOkException
:
except
NotOkException
:
return
False
return
False
def
create_user
(
self
,
password
,
keys
,
quota
):
def
create_user
(
self
,
password
,
keys
,
quota
):
self
.
_request
(
"/new/"
+
self
.
username
,
method
=
post
,
self
.
_request
(
"/new/"
,
method
=
post
,
SMBPASSWD
=
password
,
KEYS
=
keys
,
QUOTA
=
quota
)
SMBPASSWD
=
password
,
KEYS
=
keys
,
QUOTA
=
quota
)
@staticmethod
@staticmethod
...
...
circle/dashboard/views/store.py
View file @
5179872f
...
@@ -35,7 +35,8 @@ from django.views.generic import TemplateView
...
@@ -35,7 +35,8 @@ from django.views.generic import TemplateView
from
braces.views
import
LoginRequiredMixin
from
braces.views
import
LoginRequiredMixin
from
..store_api
import
Store
,
NoStoreException
,
NotOkException
from
..store_api
import
(
Store
,
NoStoreException
,
NotOkException
,
NoOrgIdException
)
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -70,6 +71,11 @@ class StoreList(LoginRequiredMixin, TemplateView):
...
@@ -70,6 +71,11 @@ class StoreList(LoginRequiredMixin, TemplateView):
return
super
(
StoreList
,
self
)
.
get
(
*
args
,
**
kwargs
)
return
super
(
StoreList
,
self
)
.
get
(
*
args
,
**
kwargs
)
except
NoStoreException
:
except
NoStoreException
:
messages
.
warning
(
self
.
request
,
_
(
"No store."
))
messages
.
warning
(
self
.
request
,
_
(
"No store."
))
except
NoOrgIdException
:
messages
.
warning
(
self
.
request
,
_
(
"Your organization ID is not set."
" To use the store, you need a"
" unique organization ID."
))
except
NotOkException
:
except
NotOkException
:
messages
.
warning
(
self
.
request
,
_
(
"Store has some problems now."
messages
.
warning
(
self
.
request
,
_
(
"Store has some problems now."
" Try again later."
))
" Try again later."
))
...
...
circle/firewall/tasks/local_tasks.py
View file @
5179872f
...
@@ -39,7 +39,7 @@ def _apply_once(name, tasks, queues, task, data):
...
@@ -39,7 +39,7 @@ def _apply_once(name, tasks, queues, task, data):
data
=
data
()
data
=
data
()
for
queue
in
queues
:
for
queue
in
queues
:
try
:
try
:
task
.
apply_async
(
args
=
data
,
queue
=
queue
,
expires
=
60
)
.
get
(
timeout
=
2
)
task
.
apply_async
(
args
=
data
,
queue
=
queue
,
expires
=
60
)
.
get
(
timeout
=
5
)
logger
.
info
(
"
%
s configuration is reloaded. (queue:
%
s)"
,
logger
.
info
(
"
%
s configuration is reloaded. (queue:
%
s)"
,
name
,
queue
)
name
,
queue
)
except
TimeoutError
as
e
:
except
TimeoutError
as
e
:
...
@@ -76,8 +76,14 @@ def reloadtask_worker():
...
@@ -76,8 +76,14 @@ def reloadtask_worker():
logger
.
info
(
"reloadtask_worker: Reload
%
s"
,
", "
.
join
(
tasks
))
logger
.
info
(
"reloadtask_worker: Reload
%
s"
,
", "
.
join
(
tasks
))
firewall_queues
=
get_firewall_queues
()
firewall_queues
=
get_firewall_queues
()
dns_queues
=
[(
"
%
s.dns"
%
i
)
for
i
in
settings
.
get
(
'dns_queues'
,
[
gethostname
()])]
dns_queues
=
settings
.
get
(
'dns_queues'
,
[
gethostname
()])
if
isinstance
(
dns_queues
,
(
str
,
unicode
)):
dns_queues
=
[
dns_queues
]
dns_queues
=
[(
"
%
s.dns"
%
i
)
for
i
in
dns_queues
]
# dns_queues = [("%s.dns" % i) for i in
# settings.get('dns_queues', [gethostname()])]
_apply_once
(
'dns'
,
tasks
,
dns_queues
,
reload_dns
,
_apply_once
(
'dns'
,
tasks
,
dns_queues
,
reload_dns
,
lambda
:
(
dns
(),
))
lambda
:
(
dns
(),
))
...
...
circle/manager/mancelery.py
View file @
5179872f
...
@@ -18,6 +18,7 @@
...
@@ -18,6 +18,7 @@
from
celery
import
Celery
from
celery
import
Celery
from
celery.signals
import
worker_ready
from
celery.signals
import
worker_ready
from
datetime
import
timedelta
from
datetime
import
timedelta
from
celery.schedules
import
crontab
from
kombu
import
Queue
,
Exchange
from
kombu
import
Queue
,
Exchange
from
os
import
getenv
from
os
import
getenv
...
@@ -52,7 +53,7 @@ celery.conf.update(
...
@@ -52,7 +53,7 @@ celery.conf.update(
'dashboard.send_email_notifications'
:
{
'dashboard.send_email_notifications'
:
{
'task'
:
'dashboard.tasks.local_periodic_tasks.'
'task'
:
'dashboard.tasks.local_periodic_tasks.'
'send_email_notifications'
,
'send_email_notifications'
,
'schedule'
:
timedelta
(
hours
=
24
),
'schedule'
:
crontab
(
minute
=
10
,
hour
=
1
),
'options'
:
{
'queue'
:
'localhost.man'
}
'options'
:
{
'queue'
:
'localhost.man'
}
},
},
}
}
...
...
circle/storage/models.py
View file @
5179872f
...
@@ -86,7 +86,7 @@ class DataStore(Model):
...
@@ -86,7 +86,7 @@ class DataStore(Model):
args
=
[
self
.
path
],
queue
=
q
)
.
get
(
timeout
=
timeout
)
args
=
[
self
.
path
],
queue
=
q
)
.
get
(
timeout
=
timeout
)
@method_cache
(
30
)
@method_cache
(
30
)
def
get_orphan_disks
(
self
,
timeout
=
1
5
):
def
get_orphan_disks
(
self
,
timeout
=
2
5
):
"""Disk image files without Disk object in the database.
"""Disk image files without Disk object in the database.
"""
"""
queue_name
=
self
.
get_remote_queue_name
(
'storage'
,
"slow"
)
queue_name
=
self
.
get_remote_queue_name
(
'storage'
,
"slow"
)
...
@@ -101,7 +101,7 @@ class DataStore(Model):
...
@@ -101,7 +101,7 @@ class DataStore(Model):
return
orphans
return
orphans
@method_cache
(
30
)
@method_cache
(
30
)
def
get_missing_disks
(
self
,
timeout
=
1
5
):
def
get_missing_disks
(
self
,
timeout
=
2
5
):
"""Disk objects without disk image files.
"""Disk objects without disk image files.
"""
"""
queue_name
=
self
.
get_remote_queue_name
(
'storage'
,
"slow"
)
queue_name
=
self
.
get_remote_queue_name
(
'storage'
,
"slow"
)
...
@@ -111,7 +111,7 @@ class DataStore(Model):
...
@@ -111,7 +111,7 @@ class DataStore(Model):
return
disks
.
exclude
(
filename__in
=
files
)
return
disks
.
exclude
(
filename__in
=
files
)
@method_cache
(
120
)
@method_cache
(
120
)
def
get_file_statistics
(
self
,
timeout
=
3
0
):
def
get_file_statistics
(
self
,
timeout
=
9
0
):
queue_name
=
self
.
get_remote_queue_name
(
'storage'
,
"slow"
)
queue_name
=
self
.
get_remote_queue_name
(
'storage'
,
"slow"
)
data
=
storage_tasks
.
get_file_statistics
.
apply_async
(
data
=
storage_tasks
.
get_file_statistics
.
apply_async
(
args
=
[
self
.
path
],
queue
=
queue_name
)
.
get
(
timeout
=
timeout
)
args
=
[
self
.
path
],
queue
=
queue_name
)
.
get
(
timeout
=
timeout
)
...
...
circle/vm/models/node.py
View file @
5179872f
...
@@ -349,7 +349,7 @@ class Node(OperatedMixin, TimeStampedModel):
...
@@ -349,7 +349,7 @@ class Node(OperatedMixin, TimeStampedModel):
continue
continue
value
=
target
[
'datapoints'
][
-
2
][
0
]
value
=
target
[
'datapoints'
][
-
2
][
0
]
retval
[
metric
]
=
float
(
value
)
retval
[
metric
]
=
float
(
value
)
except
(
KeyError
,
IndexError
,
ValueError
):
except
(
KeyError
,
IndexError
,
ValueError
,
TypeError
):
continue
continue
return
retval
return
retval
...
...
circle/vm/operations.py
View file @
5179872f
...
@@ -460,7 +460,7 @@ class DeployOperation(InstanceOperation):
...
@@ -460,7 +460,7 @@ class DeployOperation(InstanceOperation):
description
=
_
(
"Deploy virtual machine."
)
description
=
_
(
"Deploy virtual machine."
)
remote_queue
=
(
"vm"
,
"slow"
)
remote_queue
=
(
"vm"
,
"slow"
)
task
=
vm_tasks
.
deploy
task
=
vm_tasks
.
deploy
remote_timeout
=
120
def
_get_remote_args
(
self
,
**
kwargs
):
def
_get_remote_args
(
self
,
**
kwargs
):
return
[
self
.
instance
.
get_vm_desc
()]
return
[
self
.
instance
.
get_vm_desc
()]
# intentionally not calling super
# intentionally not calling super
...
...
circle/vm/tasks/local_periodic_tasks.py
View file @
5179872f
...
@@ -58,9 +58,9 @@ def garbage_collector(timeout=15):
...
@@ -58,9 +58,9 @@ def garbage_collector(timeout=15):
i
.
pk
,
unicode
(
e
))
i
.
pk
,
unicode
(
e
))
elif
(
i
.
time_of_suspend
and
now
>
i
.
time_of_suspend
and
elif
(
i
.
time_of_suspend
and
now
>
i
.
time_of_suspend
and
i
.
state
==
'RUNNING'
):
i
.
state
==
'RUNNING'
):
i
.
sleep
.
async
(
system
=
True
)
logger
.
info
(
"Expired instance
%
d suspended."
%
i
.
pk
)
logger
.
info
(
"Expired instance
%
d suspended."
%
i
.
pk
)
try
:
try
:
i
.
sleep
.
async
(
system
=
True
)
i
.
owner
.
profile
.
notify
(
i
.
owner
.
profile
.
notify
(
ugettext_noop
(
'
%(instance)
s suspended'
),
ugettext_noop
(
'
%(instance)
s suspended'
),
ugettext_noop
(
ugettext_noop
(
...
@@ -68,8 +68,10 @@ def garbage_collector(timeout=15):
...
@@ -68,8 +68,10 @@ def garbage_collector(timeout=15):
'has been suspended due to expiration. '
'has been suspended due to expiration. '
'You can resume or destroy it.'
),
'You can resume or destroy it.'
),
instance
=
i
.
name
,
url
=
i
.
get_absolute_url
())
instance
=
i
.
name
,
url
=
i
.
get_absolute_url
())
except
ActivityInProgressError
:
logger
.
error
(
"Expired instance
%
d can't be destroyed due the AtctivityInPorgressError."
,
i
.
pk
)
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
debug
(
'Could not notify owner of instance
%
d .
%
s'
,
logger
.
info
(
'Could not notify owner of instance
%
d .
%
s'
,
i
.
pk
,
unicode
(
e
))
i
.
pk
,
unicode
(
e
))
elif
i
.
is_expiring
():
elif
i
.
is_expiring
():
logger
.
debug
(
"Instance
%
d expires soon."
%
i
.
pk
)
logger
.
debug
(
"Instance
%
d expires soon."
%
i
.
pk
)
...
...
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