Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DO NOT MERGE NOW] Link statistics tutorial #1457

Closed
wants to merge 10 commits into from
2 changes: 1 addition & 1 deletion backend_core/tomato/api/misc.py
Expand Up @@ -22,7 +22,7 @@
from ..lib.userflags import Flags

def link_statistics(siteA, siteB):
return link.getStatistics(siteA, siteB)
return link.getStatisticsInfo(siteA, siteB)

def notifyAdmins(subject, text, global_contact, issue, user_orga, user_name):
api = get_backend_users_proxy()
Expand Down
56 changes: 55 additions & 1 deletion backend_core/tomato/connections.py
Expand Up @@ -24,8 +24,9 @@
from .lib import logging #@UnresolvedImport
from .lib.error import UserError, InternalError
from .lib.cache import cached #@UnresolvedImport
from .lib.constants import ActionName, StateName, TypeName
from .lib.constants import ActionName, StateName, TypeName, ConnectionDistance
from .lib.exceptionhandling import wrap_and_handle_current_exception
from .link import getStatistics

REMOVE_ACTION = "(remove)"

Expand Down Expand Up @@ -463,6 +464,58 @@ def host_info(self):
'fileserver_port': host.hostInfo.get('fileserver_port', None)
}

def link_stats(self):
if self.elementFrom.state == ST_CREATED or self.elementTo.state == ST_CREATED:
return None

hostA = self.elementFrom.host.name
siteA = self.elementFrom.host.site.name
hostB = self.elementTo.host.name
siteB = self.elementTo.host.site.name

if hostA == hostB:
distance = ConnectionDistance.INTRA_HOST
link_stats = None

else:

if siteA == siteB:
distance = ConnectionDistance.INTRA_SITE
else:
distance = ConnectionDistance.INTER_SITE

link_stats_ = getStatistics(siteA, siteB)
if link_stats_:
link_stats_info = link_stats_.quickInfo()
recent = None
average = None
for key in ["5minutes", "hour", "day", "month", "year"]:
if link_stats_info[key]:
recent = link_stats_info[key]
break
for key in ["year", "month", "day", "hour", "5minutes"]:
if link_stats_info[key]:
average = link_stats_info[key]
break
if recent or average:
link_stats = {
"recent": recent.info(),
"average": average.info()
}
else:
link_stats = None
else:
link_stats = None

return {
"hostA": hostA,
"siteA": siteA,
"hostB": hostB,
"siteB": siteB,
"distance": distance,
"statistics": link_stats
}

ACTIONS = {
Entity.REMOVE_ACTION: StatefulAction(_remove, check=checkRemove)
}
Expand All @@ -479,6 +532,7 @@ def host_info(self):
'host_elements': schema.List(items=schema.List(minLength=2, maxLength=2)),
'host_connections': schema.List(items=schema.List(minLength=2, maxLength=2))
}, required=['host_elements', 'host_connections'])),
"link_statistics": Attribute(get=link_stats, readOnly=True),
"host": Attribute(get=lambda self: self.host.name if self.host else None, readOnly=True),
"host_info": Attribute(field=host_info, readOnly=True)
}
Expand Down
40 changes: 35 additions & 5 deletions backend_core/tomato/link.py
Expand Up @@ -119,6 +119,35 @@ def add(self, measurement):
self.single.append(measurement)
self.save()

def quickInfo(self):
if self.by5minutes:
fminutes = max(self.by5minutes, key=lambda r: r.end)
else:
fminutes = None
if self.byHour:
hour = max(self.byHour, key=lambda r: r.end)
else:
hour = None
if self.byDay:
day = max(self.byDay, key=lambda r: r.end)
else:
day = None
if self.byMonth:
month = max(self.byMonth, key=lambda r: r.end)
else:
month = None
if self.byYear:
year = max(self.byYear, key=lambda r: r.end)
else:
year = None

return {
"5minutes": fminutes,
"hour": hour,
"day": day,
"month": month,
"year": year
}

pingingLock = threading.RLock()
pinging = set()
Expand Down Expand Up @@ -195,20 +224,21 @@ def get_site_pairs():
def housekeep():
exec_js(js_code("link_housekeep"), now=time.time(), types=TYPES, keep_records=KEEP_RECORDS, max_age={k: v.total_seconds() for k, v in MAX_AGE.items()})

def getStatistics(siteA, siteB): #@ReservedAssignment
def getStatistics(siteA, siteB):
_siteA = Site.get(siteA)
_siteB = Site.get(siteB)
UserError.check(_siteA is not None, UserError.ENTITY_DOES_NOT_EXIST, "site does not exist", data={"site": siteA})
UserError.check(_siteB is not None, UserError.ENTITY_DOES_NOT_EXIST, "site does not exist", data={"site": siteB})
if _siteA.id > _siteB.id:
_siteA, _siteB = _siteB, _siteA
try:
stats = LinkStatistics.objects.get(siteA=_siteA, siteB=_siteB)
return stats.info()
return LinkStatistics.objects.get(siteA=_siteA, siteB=_siteB)
except LinkStatistics.DoesNotExist:
ping(_siteA, _siteB)
stats = LinkStatistics.objects.get(siteA=_siteA, siteB=_siteB)
return stats.info()
return LinkStatistics.objects.get(siteA=_siteA, siteB=_siteB)

def getStatisticsInfo(siteA, siteB): #@ReservedAssignment
return getStatistics(siteA, siteB).info()


scheduler.scheduleMaintenance(60, get_site_pairs, lambda pair: ping(pair[0], pair[1], ignore_missing_site=True)) # every minute
Expand Down
44 changes: 22 additions & 22 deletions contrib/tutorials/basic/steps.js
Expand Up @@ -69,7 +69,7 @@
mask = {
attrs: {
state: "created",
type: "openvz"
type: "container"
},
component: "element",
operation: "create",
Expand All @@ -79,16 +79,16 @@

},
text: '<p class = "tutorialCommand">\
To add a first device to your topology, click on OpenVZ (blue screen) \
To add a first device to your topology, select the Container element (blue screen) \
in \'Common elements\' in the menu, and then click somewhere in the workspace.</p>'
},
{
text: '<p class="tutorialExplanation">\
Congratulations! You have placed your first OpenVZ device.<br />\
You can always identify OpenVZ devices by a blue screen.\
OpenVZ devices are virtual machines which use their host\'s kernel to operate, but have their own virtual file system.\
Congratulations! You have placed your first container device.<br />\
You can always identify container devices by a blue screen.\
Container-based virual machines use their host\'s kernel to operate, but have their own virtual file system, and their own processes.\
This makes them more efficient to run, but prohibits modifying the VM\'s kernel \
which also means you can only run Linux systems in OpenVZ devices.</p>\
which also means you can only run Linux systems in container devices.</p>\
<p class="tutorialExplanation">Did you notice the ? button, which just appeared in the top-right corner of this window?\
This leads you to a help page which tells you more about what you just did (Don\'t worry, it opens in a new browser tab).</p>',
help_page:'DeviceTypes',
Expand Down Expand Up @@ -127,7 +127,7 @@
mask = {
attrs: {
state: "created",
type: "kvmqm"
type: "full"
},
component: "element",
operation: "create",
Expand All @@ -137,16 +137,16 @@

},
text: '<p class="tutorialExplanation">\
You will need more devices to get a whole topology. This time, let\'s create a KVM device.</p>\
You will need more devices to get a whole topology. This time, let\'s create a full-virtualization device.</p>\
<p class="tutorialCommand">\
Click KVM (green screen) in Common elements in the menu above, and the place it in the editor by\
Click "Full Virt." (green screen) in Common elements in the menu above, and the place it in the editor by\
clicking somewhere into the white.</p>'
},
{
text: '<p class="tutorialExplanation">\
You just created a KVM device.\
KVM devices can be identified by a green screen.\
Contrary to OpenVZ, KVM devices run completely separated from their host systems.\
You just created a full-virtualization device.\
Full-virtualization devices can be identified by a green screen.\
Contrary to containers, fully virtualized VMs run completely separated from their host systems.\
This means that you can modify the kernel and/or use any operating system.</p>',
skip_button:'continue'
},
Expand Down Expand Up @@ -316,25 +316,25 @@
{
trigger:function(obj) {

mask_openvz = {
mask_container = {
object: { data: {
type: "openvz"
type: "container"
}},
component: "element",
operation: "remove",
phase: "end"
};

mask_kvmqm = {
mask_full = {
object: { data: {
type: "kvmqm"
type: "full"
}},
component: "element",
operation: "remove",
phase: "end"
};

return compareToMask(obj,mask_openvz) || compareToMask(obj,mask_kvmqm);
return compareToMask(obj,mask_container) || compareToMask(obj,mask_full);

},
text: '<p class="tutorialExplanation">\
Expand All @@ -347,25 +347,25 @@
{
trigger:function(obj) {

mask_openvz = {
mask_container = {
object: { data: {
type: "openvz"
type: "container"
}},
component: "element",
operation: "remove",
phase: "end"
};

mask_kvmqm = {
mask_full = {
object: { data: {
type: "kvmqm"
type: "full"
}},
component: "element",
operation: "remove",
phase: "end"
};

return compareToMask(obj,mask_openvz) || compareToMask(obj,mask_kvmqm);
return compareToMask(obj,mask_container) || compareToMask(obj,mask_full);

},
text: '<p class="tutorialCommand">\
Expand Down
10 changes: 5 additions & 5 deletions contrib/tutorials/chat/steps.js
Expand Up @@ -18,10 +18,10 @@
skip_button: 'Continue'
},
{
text: '<p class="tutorialExplanation">As first step we add two virtual machines to the topology. These virtual machines will use OpenVZ technology since we only want to run a simple program on it.<br/>\
text: '<p class="tutorialExplanation">As first step we add two virtual machines to the topology. These virtual machines will use container-based virtualization technology since we only want to run a simple program on it.<br/>\
Click on the blue computer icon on the right of the menu and then click into the work space to position that element. You can later move it by dragging the icon in the work space.<br/>\
You can move this tutorial window if it covers your work space.</p>\
<p class="tutorialCommand">Add two OpenVZ devices to your topology</p>',
<p class="tutorialCommand">Add two container devices to your topology</p>',
trigger: function(event) {
data = getTutorialData();
if (! data.tmp) data.tmp = 0;
Expand All @@ -30,7 +30,7 @@
component: "element",
phase: "end",
attrs: {
type: "openvz"
type: "container"
},
});
if(match) data.tmp++;
Expand Down Expand Up @@ -448,7 +448,7 @@ Note that you can not type any text into the consoles of these agents as the Rep
help_page: 'LinkEmulation'
},
{
text: '<p class="tutorialExplanation">Now we will add a delay of 2 seconds to a link and check if we can see the difference. Open the attributes of the link of one OpenVZ VM as you learned in the the first part. Enable link emulation and add a delay of 2000 ms on one of the directions.</p>\
text: '<p class="tutorialExplanation">Now we will add a delay of 2 seconds to a link and check if we can see the difference. Open the attributes of the link of one container VM as you learned in the the first part. Enable link emulation and add a delay of 2000 ms on one of the directions.</p>\
<p class="tutorialCommand">Add 2 seconds delay to one link</p>',
trigger: function(event) {
var data = getTutorialData();
Expand All @@ -471,7 +471,7 @@ Note that you can not type any text into the consoles of these agents as the Rep
help_page: 'LinkEmulation'
},
{
text: '<p class="tutorialExplanation">You should see the delay when you send messages between your OpenVZ VMs. The delay should only exist in one direction.<br/>\
text: '<p class="tutorialExplanation">You should see the delay when you send messages between your container VMs. The delay should only exist in one direction.<br/>\
Now you can play around with the settings a little. Maybe add some jitter to the connection. If you apply packet duplication or packet loss you can use the sequence numbers to check this functionality.</p>\
<p class="tutorialCommand">Click continue when you want to continue</p>',
skip_button: 'Continue',
Expand Down
8 changes: 4 additions & 4 deletions contrib/tutorials/device_data_access/steps.js
Expand Up @@ -61,7 +61,7 @@
});
},
text: '<p class="tutorialExplanation">\
Now after the devices started right click on the left device (openvz1) and use <pre>&gt; Executable archive &gt; Upload Archive</pre> to upload and run the archive on your device</p>\
Now after the devices started right click on the left device (container1) and use <pre>&gt; Executable archive &gt; Upload Archive</pre> to upload and run the archive on your device</p>\
<p class="tutorialExplanation">\
After the upload, the archive will be automatically executed by running the <i>auto_exec.sh</i> file inside it if the file exists.\
Executable archives are a good way to run programms on a device. If you want to learn more about them feel free to visite the <i>Executable Archives tutorial</i>.</p>',
Expand Down Expand Up @@ -177,9 +177,9 @@ The simulation will create some output on your console and also create data in a
return match;
},
text: '<p clas s="tutorialExplanation">\
You can upload any image to a device of the same technology. You can not use images accross technologies (e.g., you can\'t upload an OpenVZ image to a KVM device, and vice versa).</p>\
You can upload any image to a device of the same technology. You can not use images accross technologies (e.g., you can\'t upload a container image to a full-virtualization device, and vice versa).</p>\
<p class="tutorialCommand">\
Upload your image again to the second device (openvz2).</p>\
Upload your image again to the second device (container2).</p>\
<p class="tutorialExplanation">\
You can skip this step if a big upload might cause you trouble. Then please run the executable archive on the second device so we can continue the tutorial.</p>\
<p class="tutorialExplanation">\
Expand Down Expand Up @@ -218,7 +218,7 @@ The simulation will create some output on your console and also create data in a
text: '<p class="tutorialExplanation">\
SSH is deactivated by default. In order to use it we have to remote connect to our device (with NoVNC) and run <i>ssh-enable</i>. <br/> Let\'s do it, so we can use SSH to get access to our device.</p>\
<p class="tutorialCommand">\
Use NoVNC to run <i>ssh-enable</i> on the second device (openvz2). Press "Continue" if you did so.</p>',
Use NoVNC to run <i>ssh-enable</i> on the second device (container2). Press "Continue" if you did so.</p>',
skip_button: "Continue"
},
{
Expand Down
8 changes: 4 additions & 4 deletions contrib/tutorials/device_data_access/topology.json
Expand Up @@ -74,8 +74,8 @@
"parent": null,
"attrs": {
"profile": "normal",
"name": "openvz2",
"hostname": "openvz2",
"name": "container2",
"hostname": "container2",
"site": null,
"_pos": {
"y": 0.042092427720118612,
Expand Down Expand Up @@ -104,8 +104,8 @@
"parent": null,
"attrs": {
"profile": "normal",
"name": "openvz1",
"hostname": "openvz1",
"name": "container1",
"hostname": "container1",
"site": null,
"_pos": {
"y": 0.036617975165374086,
Expand Down
2 changes: 1 addition & 1 deletion contrib/tutorials/executable_archives/topology.json
Expand Up @@ -12,7 +12,7 @@
"attrs": {
"profile": "normal",
"site": null,
"name": "openvz1",
"name": "container1",
"template": "debian-6.0_x86",
"_pos": {
"y": 0.3181818181818182,
Expand Down