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
Commit
cec0fef7
authored
7 years ago
by
cloud
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added periodic task for vm auto migration
parent
eae91fdd
Pipeline
#636
passed with stage
in 0 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
88 additions
and
5 deletions
+88
-5
circle/circle/settings/base.py
+2
-0
circle/vm/models/instance.py
+47
-0
circle/vm/tasks/local_periodic_tasks.py
+39
-5
No files found.
circle/circle/settings/base.py
View file @
cec0fef7
...
@@ -590,3 +590,5 @@ TWO_FACTOR_ISSUER = get_env_variable("TWO_FACTOR_ISSUER", "CIRCLE")
...
@@ -590,3 +590,5 @@ TWO_FACTOR_ISSUER = get_env_variable("TWO_FACTOR_ISSUER", "CIRCLE")
# Default value is every day at midnight
# Default value is every day at midnight
AUTO_MIGRATION_CRONTAB
=
get_env_variable
(
"AUTO_MIGRATION_CRONTAB"
,
"0 0 * * *"
)
AUTO_MIGRATION_CRONTAB
=
get_env_variable
(
"AUTO_MIGRATION_CRONTAB"
,
"0 0 * * *"
)
AUTO_MIGRATION_TIME_LIMIT_IN_HOURS
=
(
get_env_variable
(
"AUTO_MIGRATION_TIME_LIMIT_IN_HOURS"
,
"2"
))
This diff is collapsed.
Click to expand it.
circle/vm/models/instance.py
View file @
cec0fef7
...
@@ -865,6 +865,53 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
...
@@ -865,6 +865,53 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
def
metric_prefix
(
self
):
def
metric_prefix
(
self
):
return
'vm.
%
s'
%
self
.
vm_name
return
'vm.
%
s'
%
self
.
vm_name
class
MonitorUnavailableException
(
Exception
):
"""Exception for monitor_info()
Indicates the unavailability of the monitoring server.
"""
pass
def
monitor_info
(
self
):
metrics
=
(
'cpu.percent'
,
'memory.usage'
)
prefix
=
self
.
metric_prefix
params
=
[(
'target'
,
'
%
s.
%
s'
%
(
prefix
,
metric
))
for
metric
in
metrics
]
params
.
append
((
'from'
,
'-5min'
))
params
.
append
((
'format'
,
'json'
))
try
:
logger
.
info
(
'
%
s
%
s'
,
settings
.
GRAPHITE_URL
,
params
)
response
=
requests
.
get
(
settings
.
GRAPHITE_URL
,
params
=
params
)
retval
=
{}
for
target
in
response
.
json
():
# Example:
# {"target": "circle.vm.{name}.cpu.usage",
# "datapoints": [[0.6, 1403045700], [0.5, 1403045760]
try
:
metric
=
target
[
'target'
]
if
metric
.
startswith
(
prefix
):
metric
=
metric
[
len
(
prefix
):]
else
:
continue
value
=
target
[
'datapoints'
][
-
2
][
0
]
retval
[
metric
]
=
float
(
value
)
except
(
KeyError
,
IndexError
,
ValueError
):
continue
return
retval
except
Exception
:
logger
.
exception
(
'Monitor server unavailable: '
)
raise
Instance
.
MonitorUnavailableException
()
def
cpu_usage
(
self
):
return
self
.
monitor_info
()
.
get
(
'cpu.percent'
)
def
ram_usage
(
self
):
return
self
.
monitor_info
()
.
get
(
'memory.usage'
)
@contextmanager
@contextmanager
def
activity
(
self
,
code_suffix
,
readable_name
,
on_abort
=
None
,
def
activity
(
self
,
code_suffix
,
readable_name
,
on_abort
=
None
,
on_commit
=
None
,
task_uuid
=
None
,
user
=
None
,
on_commit
=
None
,
task_uuid
=
None
,
user
=
None
,
...
...
This diff is collapsed.
Click to expand it.
circle/vm/tasks/local_periodic_tasks.py
View file @
cec0fef7
...
@@ -17,7 +17,9 @@
...
@@ -17,7 +17,9 @@
import
logging
import
logging
from
django.utils
import
timezone
from
django.utils
import
timezone
from
datetime
import
timedelta
from
django.utils.translation
import
ugettext_noop
from
django.utils.translation
import
ugettext_noop
from
django.conf
import
settings
from
manager.mancelery
import
celery
from
manager.mancelery
import
celery
from
vm.models
import
Node
,
Instance
from
vm.models
import
Node
,
Instance
...
@@ -79,8 +81,40 @@ def garbage_collector(timeout=15):
...
@@ -79,8 +81,40 @@ def garbage_collector(timeout=15):
@celery.task
(
ignore_result
=
True
)
@celery.task
(
ignore_result
=
True
)
def
auto_migrate
():
# Dummy implementation
def
auto_migrate
():
import
time
"""Auto migration task for runtime scaling
logger
.
info
(
"Auto migration has started."
)
"""
time
.
sleep
(
10
)
time_limit
=
settings
.
AUTO_MIGRATION_TIME_LIMIT_IN_HOURS
logger
.
info
(
"Auto migration has finished."
)
available_time
=
timedelta
(
hours
=
int
(
time_limit
))
deadline
=
timezone
.
now
()
+
available_time
while
timezone
.
now
()
<
deadline
:
migrate_one
()
def
migrate_one
():
"""Migrate a VM syncronously.
The target node chosen by the scheduler.
"""
nodes
=
[
n
for
n
in
Node
.
objects
.
filter
(
enabled
=
True
)
if
n
.
online
]
node_max_cpu
=
max
(
nodes
,
key
=
lambda
x
:
x
.
cpu_usage
/
x
.
cpu_weight
)
node_max_ram
=
max
(
nodes
,
key
=
lambda
x
:
x
.
ram_usage
/
x
.
ram_weight
)
if
node_max_cpu
.
cpu_usage
>
node_max_ram
.
ram_usage
:
try
:
instance_to_migrate
=
max
(
Instance
.
objects
.
filter
(
node
=
node_max_cpu
.
pk
),
key
=
lambda
x
:
x
.
cpu_usage
())
instance_to_migrate
.
migrate
(
system
=
True
)
except
Instance
.
MonitorUnavailableException
:
instance_to_migrate
=
max
(
Instance
.
objects
.
filter
(
node
=
node_max_cpu
.
pk
),
key
=
(
lambda
x
:
x
.
get_vm_desc
()[
"vcpu"
]
*
x
.
get_vm_desc
()[
"cpu_share"
]))
instance_to_migrate
.
migrate
(
system
=
True
)
else
:
try
:
instance_to_migrate
=
max
(
Instance
.
objects
.
filter
(
node
=
node_max_ram
.
pk
),
key
=
lambda
x
:
x
.
ram_usage
())
instance_to_migrate
.
migrate
(
system
=
True
)
except
Instance
.
MonitorUnavailableException
:
instance_to_migrate
=
max
(
Instance
.
objects
.
filter
(
node
=
node_max_cpu
.
pk
),
key
=
lambda
x
:
x
.
get_vm_desc
()[
"memory"
])
instance_to_migrate
.
migrate
(
system
=
True
)
This diff is collapsed.
Click to expand it.
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