Revision 56a1134d
b/snf-cyclades-app/synnefo/logic/management/commands/backend-add.py | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or without |
|
4 |
# modification, are permitted provided that the following conditions |
|
5 |
# are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above copyright |
|
8 |
# notice, this list of conditions and the following disclaimer. |
|
9 |
# |
|
10 |
# 2. Redistributions in binary form must reproduce the above copyright |
|
11 |
# notice, this list of conditions and the following disclaimer in the |
|
12 |
# documentation and/or other materials provided with the distribution. |
|
13 |
# |
|
14 |
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
15 |
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
16 |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
17 |
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
18 |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
19 |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
20 |
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
21 |
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
22 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
23 |
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
24 |
# SUCH DAMAGE. |
|
25 |
# |
|
26 |
# The views and conclusions contained in the software and documentation are |
|
27 |
# those of the authors and should not be interpreted as representing official |
|
28 |
# policies, either expressed or implied, of GRNET S.A. |
|
29 |
# |
|
30 |
|
|
31 |
from optparse import make_option |
|
32 |
from django.core.management.base import BaseCommand, CommandError |
|
33 |
|
|
34 |
from synnefo.db.models import Backend, Network, BackendNetwork |
|
35 |
from django.db.utils import IntegrityError |
|
36 |
from synnefo.logic.backend import (get_physical_resources, |
|
37 |
update_resources, |
|
38 |
create_client, |
|
39 |
create_network_synced) |
|
40 |
from synnefo.util.rapi import GanetiApiError |
|
41 |
|
|
42 |
|
|
43 |
class Command(BaseCommand): |
|
44 |
can_import_settings = True |
|
45 |
|
|
46 |
help = 'Create a new backend.' |
|
47 |
output_transaction = True # The management command runs inside |
|
48 |
# an SQL transaction |
|
49 |
option_list = BaseCommand.option_list + ( |
|
50 |
make_option('--clustername', dest='clustername'), |
|
51 |
make_option('--port', dest='port', default=5080), |
|
52 |
make_option('--user', dest='username'), |
|
53 |
make_option('--pass', dest='password'), |
|
54 |
make_option('--drained', action='store_true', |
|
55 |
dest='drained', default=False, |
|
56 |
help="Set as drained to exclude from allocations"), |
|
57 |
make_option('--no-check', action='store_false', |
|
58 |
dest='check', default=True, |
|
59 |
help="Do not perform credentials check and resources update"), |
|
60 |
make_option('--no-init', action='store_false', |
|
61 |
dest='init', default=True, |
|
62 |
help="Do not perform initialization of the Backend Model") |
|
63 |
) |
|
64 |
|
|
65 |
def handle(self, **options): |
|
66 |
clustername = options['clustername'] |
|
67 |
port = options['port'] |
|
68 |
username = options['username'] |
|
69 |
password = options['password'] |
|
70 |
drained = options['drained'] |
|
71 |
|
|
72 |
if not (clustername and username and password): |
|
73 |
raise CommandError("Clustername, user and pass must be supplied") |
|
74 |
|
|
75 |
# Ensure correctness of credentials |
|
76 |
if options['check']: |
|
77 |
self.stdout.write('Checking connectivity and credentials.\n') |
|
78 |
try: |
|
79 |
client = create_client(clustername, port, username, password) |
|
80 |
# This command will raise an exception if there is no |
|
81 |
# write-access |
|
82 |
client.ModifyCluster() |
|
83 |
except GanetiApiError as e: |
|
84 |
self.stdout.write('Check failed:\n%s\n' % e) |
|
85 |
return |
|
86 |
else: |
|
87 |
self.stdout.write('Check passed.\n') |
|
88 |
|
|
89 |
# Create the new backend in database |
|
90 |
try: |
|
91 |
backend = Backend.objects.create(clustername=clustername, |
|
92 |
port=port, |
|
93 |
username=username, |
|
94 |
password=password, |
|
95 |
drained=drained) |
|
96 |
except IntegrityError as e: |
|
97 |
raise CommandError("Cannot create backend: %s\n" % e) |
|
98 |
|
|
99 |
self.stdout.write('\nSuccessfully created backend with id %d\n' % |
|
100 |
backend.id) |
|
101 |
|
|
102 |
if not options['check']: |
|
103 |
return |
|
104 |
|
|
105 |
self.stdout.write('\rRetrieving backend resources:\n') |
|
106 |
resources = get_physical_resources(backend) |
|
107 |
attr = ['mfree', 'mtotal', 'dfree', 'dtotal', 'pinst_cnt', 'ctotal'] |
|
108 |
self.stdout.write('----------------------------\n') |
|
109 |
for a in attr: |
|
110 |
self.stdout.write(a.ljust(12) + ' : ' + str(resources[a]) + '\n') |
|
111 |
update_resources(backend, resources) |
|
112 |
|
|
113 |
if not options['init']: |
|
114 |
return |
|
115 |
|
|
116 |
networks = Network.objects.filter(deleted=False) |
|
117 |
|
|
118 |
self.stdout.write('\nCreating the follow networks:\n') |
|
119 |
fields = ('Name', 'Subnet', 'Gateway', 'Mac Prefix', 'Public') |
|
120 |
columns = (20, 16, 16, 16, 10) |
|
121 |
line = ' '.join(f.ljust(c) for f, c in zip(fields, columns)) |
|
122 |
sep = '-' * len(line) |
|
123 |
self.stdout.write(sep + '\n') |
|
124 |
self.stdout.write(line + '\n') |
|
125 |
self.stdout.write(sep + '\n') |
|
126 |
|
|
127 |
for net in networks: |
|
128 |
fields = (net.backend_id, str(net.subnet), str(net.gateway), |
|
129 |
str(net.mac_prefix), str(net.public)) |
|
130 |
line = ' '.join(f.ljust(c) for f, c in zip(fields, columns)) |
|
131 |
self.stdout.write(line + '\n') |
|
132 |
self.stdout.write(sep + '\n\n') |
|
133 |
|
|
134 |
for net in networks: |
|
135 |
BackendNetwork.objects.create(network=net, backend=backend) |
|
136 |
result = create_network_synced(net, backend) |
|
137 |
if result[0] != "success": |
|
138 |
self.stdout.write('\nError Creating Network %s: %s\n' %\ |
|
139 |
(net.backend_id, result[1])) |
b/snf-cyclades-app/synnefo/logic/management/commands/backend-list.py | ||
---|---|---|
1 |
# Copyright 2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from optparse import make_option |
|
35 |
from django.core.management.base import BaseCommand, CommandError |
|
36 |
|
|
37 |
from synnefo.db.models import Backend |
|
38 |
|
|
39 |
|
|
40 |
class Command(BaseCommand): |
|
41 |
help = "List backends" |
|
42 |
|
|
43 |
option_list = BaseCommand.option_list + ( |
|
44 |
make_option('-c', |
|
45 |
action='store_true', |
|
46 |
dest='csv', |
|
47 |
default=False, |
|
48 |
help="Use pipes to separate values"), |
|
49 |
) |
|
50 |
|
|
51 |
def handle(self, *args, **options): |
|
52 |
if args: |
|
53 |
raise CommandError("Command doesn't accept any arguments") |
|
54 |
|
|
55 |
backends = Backend.objects.order_by('id') |
|
56 |
|
|
57 |
labels = ('id', 'clustername', 'port', 'username', "vm's", 'drained', |
|
58 |
'offline') |
|
59 |
columns = (3, 50, 5, 10, 4, 6, 6) |
|
60 |
|
|
61 |
if not options['csv']: |
|
62 |
line = ' '.join(l.rjust(w) for l, w in zip(labels, columns)) |
|
63 |
sep = '-' * len(line) |
|
64 |
self.stdout.write(sep + '\n') |
|
65 |
self.stdout.write(line + '\n') |
|
66 |
self.stdout.write(sep + '\n') |
|
67 |
|
|
68 |
for backend in backends: |
|
69 |
id = str(backend.id) |
|
70 |
vms = str(backend.virtual_machines.filter(deleted=False).count()) |
|
71 |
fields = (id, backend.clustername, str(backend.port), |
|
72 |
backend.username, vms, str(backend.drained), |
|
73 |
str(backend.offline)) |
|
74 |
|
|
75 |
if options['csv']: |
|
76 |
line = '|'.join(fields) |
|
77 |
else: |
|
78 |
line = ' '.join(f.rjust(w) for f, w in zip(fields, columns)) |
|
79 |
|
|
80 |
self.stdout.write(line.encode('utf8') + '\n') |
b/snf-cyclades-app/synnefo/logic/management/commands/backend-modify.py | ||
---|---|---|
1 |
# Copyright 2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from optparse import make_option |
|
35 |
from django.core.management.base import BaseCommand, CommandError |
|
36 |
|
|
37 |
from synnefo.db.models import Backend |
|
38 |
|
|
39 |
|
|
40 |
class Command(BaseCommand): |
|
41 |
args = "<backend ID>" |
|
42 |
help = "Modify a backend" |
|
43 |
|
|
44 |
option_list = BaseCommand.option_list + ( |
|
45 |
make_option('--clustername', |
|
46 |
dest='clustername', |
|
47 |
help="Set backend's clustername"), |
|
48 |
make_option('--port', |
|
49 |
dest='port', |
|
50 |
help="Set backend's port"), |
|
51 |
make_option('--username', |
|
52 |
dest='username', |
|
53 |
help="Set backend'username"), |
|
54 |
make_option('--password', |
|
55 |
dest='password', |
|
56 |
help="Set backend's password"), |
|
57 |
make_option('--drained', |
|
58 |
dest='drained', |
|
59 |
action='store_true', |
|
60 |
default=False, |
|
61 |
help="Set the backend as drained to exclude from allocation "\ |
|
62 |
"operations"), |
|
63 |
make_option('--no-drained', |
|
64 |
dest='drained', |
|
65 |
action='store_false'), |
|
66 |
make_option('--offline', |
|
67 |
dest='offline', |
|
68 |
action='store_true', |
|
69 |
default=False, |
|
70 |
help="Set the backend as offline to not communicate in order "\ |
|
71 |
"to avoid delays"), |
|
72 |
make_option('--no-offline', |
|
73 |
dest='offline', |
|
74 |
action='store_false') |
|
75 |
) |
|
76 |
|
|
77 |
def handle(self, *args, **options): |
|
78 |
if len(args) != 1: |
|
79 |
raise CommandError("Please provide a backend ID") |
|
80 |
|
|
81 |
try: |
|
82 |
backend_id = int(args[0]) |
|
83 |
backend = Backend.objects.get(id=backend_id) |
|
84 |
except ValueError: |
|
85 |
raise CommandError("Invalid backend ID") |
|
86 |
except Backend.DoesNotExist: |
|
87 |
raise CommandError("Backend not found in DB") |
|
88 |
|
|
89 |
# Ensure fields correspondence with options and Backend model |
|
90 |
fields = ('clustername', 'port', 'username', 'password', 'drained', |
|
91 |
'offline') |
|
92 |
for field in fields: |
|
93 |
value = options.get(field) |
|
94 |
if value is not None: |
|
95 |
backend.__setattr__(field, value) |
|
96 |
|
|
97 |
backend.save() |
b/snf-cyclades-app/synnefo/logic/management/commands/backend-update-status.py | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or without |
|
4 |
# modification, are permitted provided that the following conditions |
|
5 |
# are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above copyright |
|
8 |
# notice, this list of conditions and the following disclaimer. |
|
9 |
# |
|
10 |
# 2. Redistributions in binary form must reproduce the above copyright |
|
11 |
# notice, this list of conditions and the following disclaimer in the |
|
12 |
# documentation and/or other materials provided with the distribution. |
|
13 |
# |
|
14 |
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
15 |
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
16 |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
17 |
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
18 |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
19 |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
20 |
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
21 |
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
22 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
23 |
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
24 |
# SUCH DAMAGE. |
|
25 |
# |
|
26 |
# The views and conclusions contained in the software and documentation are |
|
27 |
# those of the authors and should not be interpreted as representing official |
|
28 |
# policies, either expressed or implied, of GRNET S.A. |
|
29 |
# |
|
30 |
|
|
31 |
from optparse import make_option |
|
32 |
from django.core.management.base import BaseCommand, CommandError |
|
33 |
from synnefo import settings |
|
34 |
import datetime |
|
35 |
|
|
36 |
from synnefo.db.models import Backend |
|
37 |
from synnefo.logic.backend import update_resources |
|
38 |
|
|
39 |
|
|
40 |
class Command(BaseCommand): |
|
41 |
can_import_settings = True |
|
42 |
|
|
43 |
help = "Update backend statistics, which are used for instance allocation." |
|
44 |
output_transaction = True # The management command runs inside |
|
45 |
# an SQL transaction |
|
46 |
option_list = BaseCommand.option_list + ( |
|
47 |
make_option('--backend_id', dest='backend_id', |
|
48 |
help="Update statistics of only this backend"), |
|
49 |
make_option('--older_than', dest='older_than', metavar="MINUTES", |
|
50 |
help="Update only backends that have not been updated for\ |
|
51 |
MINUTES. Set to 0 to force update.") |
|
52 |
) |
|
53 |
|
|
54 |
def handle(self, **options): |
|
55 |
|
|
56 |
if options['backend_id']: |
|
57 |
try: |
|
58 |
backend_id = int(options['backend_id']) |
|
59 |
backends = [Backend.objects.get(id=backend_id)] |
|
60 |
except ValueError: |
|
61 |
raise CommandError("Wrong backend ID") |
|
62 |
except Backend.DoesNotExist: |
|
63 |
raise CommandError("Backend not found in DB") |
|
64 |
else: |
|
65 |
# XXX:filter drained ? |
|
66 |
backends = Backend.objects.all() |
|
67 |
|
|
68 |
now = datetime.datetime.now() |
|
69 |
if options['older_than'] is not None: |
|
70 |
minutes = int(options['older_than']) |
|
71 |
else: |
|
72 |
minutes = settings.BACKEND_REFRESH_MIN |
|
73 |
|
|
74 |
delta = datetime.timedelta(minutes=minutes) |
|
75 |
|
|
76 |
for b in backends: |
|
77 |
if now > b.updated + delta: |
|
78 |
update_resources(b) |
|
79 |
print 'Successfully updated backend with id: %d' % b.id |
|
80 |
else: |
|
81 |
print 'Backend %d does not need update' % b.id |
/dev/null | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or without |
|
4 |
# modification, are permitted provided that the following conditions |
|
5 |
# are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above copyright |
|
8 |
# notice, this list of conditions and the following disclaimer. |
|
9 |
# |
|
10 |
# 2. Redistributions in binary form must reproduce the above copyright |
|
11 |
# notice, this list of conditions and the following disclaimer in the |
|
12 |
# documentation and/or other materials provided with the distribution. |
|
13 |
# |
|
14 |
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
15 |
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
16 |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
17 |
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
18 |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
19 |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
20 |
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
21 |
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
22 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
23 |
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
24 |
# SUCH DAMAGE. |
|
25 |
# |
|
26 |
# The views and conclusions contained in the software and documentation are |
|
27 |
# those of the authors and should not be interpreted as representing official |
|
28 |
# policies, either expressed or implied, of GRNET S.A. |
|
29 |
# |
|
30 |
|
|
31 |
from optparse import make_option |
|
32 |
from django.core.management.base import BaseCommand, CommandError |
|
33 |
|
|
34 |
from synnefo.db.models import Backend, Network, BackendNetwork |
|
35 |
from django.db.utils import IntegrityError |
|
36 |
from synnefo.logic.backend import (get_physical_resources, |
|
37 |
update_resources, |
|
38 |
create_client, |
|
39 |
create_network_synced) |
|
40 |
from synnefo.util.rapi import GanetiApiError |
|
41 |
|
|
42 |
|
|
43 |
class Command(BaseCommand): |
|
44 |
can_import_settings = True |
|
45 |
|
|
46 |
help = 'Create a new backend.' |
|
47 |
output_transaction = True # The management command runs inside |
|
48 |
# an SQL transaction |
|
49 |
option_list = BaseCommand.option_list + ( |
|
50 |
make_option('--clustername', dest='clustername'), |
|
51 |
make_option('--port', dest='port', default=5080), |
|
52 |
make_option('--user', dest='username'), |
|
53 |
make_option('--pass', dest='password'), |
|
54 |
make_option('--drained', action='store_true', |
|
55 |
dest='drained', default=False, |
|
56 |
help="Set as drained to exclude from allocations"), |
|
57 |
make_option('--no-check', action='store_false', |
|
58 |
dest='check', default=True, |
|
59 |
help="Do not perform credentials check and resources update"), |
|
60 |
make_option('--no-init', action='store_false', |
|
61 |
dest='init', default=True, |
|
62 |
help="Do not perform initialization of the Backend Model") |
|
63 |
) |
|
64 |
|
|
65 |
def handle(self, **options): |
|
66 |
clustername = options['clustername'] |
|
67 |
port = options['port'] |
|
68 |
username = options['username'] |
|
69 |
password = options['password'] |
|
70 |
drained = options['drained'] |
|
71 |
|
|
72 |
if not (clustername and username and password): |
|
73 |
raise CommandError("Clustername, user and pass must be supplied") |
|
74 |
|
|
75 |
# Ensure correctness of credentials |
|
76 |
if options['check']: |
|
77 |
self.stdout.write('Checking connectivity and credentials.\n') |
|
78 |
try: |
|
79 |
client = create_client(clustername, port, username, password) |
|
80 |
# This command will raise an exception if there is no |
|
81 |
# write-access |
|
82 |
client.ModifyCluster() |
|
83 |
except GanetiApiError as e: |
|
84 |
self.stdout.write('Check failed:\n%s\n' % e) |
|
85 |
return |
|
86 |
else: |
|
87 |
self.stdout.write('Check passed.\n') |
|
88 |
|
|
89 |
# Create the new backend in database |
|
90 |
try: |
|
91 |
backend = Backend.objects.create(clustername=clustername, |
|
92 |
port=port, |
|
93 |
username=username, |
|
94 |
password=password, |
|
95 |
drained=drained) |
|
96 |
except IntegrityError as e: |
|
97 |
raise CommandError("Cannot create backend: %s\n" % e) |
|
98 |
|
|
99 |
self.stdout.write('\nSuccessfully created backend with id %d\n' % |
|
100 |
backend.id) |
|
101 |
|
|
102 |
if not options['check']: |
|
103 |
return |
|
104 |
|
|
105 |
self.stdout.write('\rRetrieving backend resources:\n') |
|
106 |
resources = get_physical_resources(backend) |
|
107 |
attr = ['mfree', 'mtotal', 'dfree', 'dtotal', 'pinst_cnt', 'ctotal'] |
|
108 |
self.stdout.write('----------------------------\n') |
|
109 |
for a in attr: |
|
110 |
self.stdout.write(a.ljust(12) + ' : ' + str(resources[a]) + '\n') |
|
111 |
update_resources(backend, resources) |
|
112 |
|
|
113 |
if not options['init']: |
|
114 |
return |
|
115 |
|
|
116 |
networks = Network.objects.filter(deleted=False) |
|
117 |
|
|
118 |
self.stdout.write('\nCreating the follow networks:\n') |
|
119 |
fields = ('Name', 'Subnet', 'Gateway', 'Mac Prefix', 'Public') |
|
120 |
columns = (20, 16, 16, 16, 10) |
|
121 |
line = ' '.join(f.ljust(c) for f, c in zip(fields, columns)) |
|
122 |
sep = '-' * len(line) |
|
123 |
self.stdout.write(sep + '\n') |
|
124 |
self.stdout.write(line + '\n') |
|
125 |
self.stdout.write(sep + '\n') |
|
126 |
|
|
127 |
for net in networks: |
|
128 |
fields = (net.backend_id, str(net.subnet), str(net.gateway), |
|
129 |
str(net.mac_prefix), str(net.public)) |
|
130 |
line = ' '.join(f.ljust(c) for f, c in zip(fields, columns)) |
|
131 |
self.stdout.write(line + '\n') |
|
132 |
self.stdout.write(sep + '\n\n') |
|
133 |
|
|
134 |
for net in networks: |
|
135 |
BackendNetwork.objects.create(network=net, backend=backend) |
|
136 |
result = create_network_synced(net, backend) |
|
137 |
if result[0] != "success": |
|
138 |
self.stdout.write('\nError Creating Network %s: %s\n' %\ |
|
139 |
(net.backend_id, result[1])) |
/dev/null | ||
---|---|---|
1 |
# Copyright 2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from optparse import make_option |
|
35 |
from django.core.management.base import BaseCommand, CommandError |
|
36 |
|
|
37 |
from synnefo.db.models import Backend |
|
38 |
|
|
39 |
|
|
40 |
class Command(BaseCommand): |
|
41 |
help = "List backends" |
|
42 |
|
|
43 |
option_list = BaseCommand.option_list + ( |
|
44 |
make_option('-c', |
|
45 |
action='store_true', |
|
46 |
dest='csv', |
|
47 |
default=False, |
|
48 |
help="Use pipes to separate values"), |
|
49 |
) |
|
50 |
|
|
51 |
def handle(self, *args, **options): |
|
52 |
if args: |
|
53 |
raise CommandError("Command doesn't accept any arguments") |
|
54 |
|
|
55 |
backends = Backend.objects.order_by('id') |
|
56 |
|
|
57 |
labels = ('id', 'clustername', 'port', 'username', "vm's", 'drained', |
|
58 |
'offline') |
|
59 |
columns = (3, 50, 5, 10, 4, 6, 6) |
|
60 |
|
|
61 |
if not options['csv']: |
|
62 |
line = ' '.join(l.rjust(w) for l, w in zip(labels, columns)) |
|
63 |
sep = '-' * len(line) |
|
64 |
self.stdout.write(sep + '\n') |
|
65 |
self.stdout.write(line + '\n') |
|
66 |
self.stdout.write(sep + '\n') |
|
67 |
|
|
68 |
for backend in backends: |
|
69 |
id = str(backend.id) |
|
70 |
vms = str(backend.virtual_machines.filter(deleted=False).count()) |
|
71 |
fields = (id, backend.clustername, str(backend.port), |
|
72 |
backend.username, vms, str(backend.drained), |
|
73 |
str(backend.offline)) |
|
74 |
|
|
75 |
if options['csv']: |
|
76 |
line = '|'.join(fields) |
|
77 |
else: |
|
78 |
line = ' '.join(f.rjust(w) for f, w in zip(fields, columns)) |
|
79 |
|
|
80 |
self.stdout.write(line.encode('utf8') + '\n') |
/dev/null | ||
---|---|---|
1 |
# Copyright 2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from optparse import make_option |
|
35 |
from django.core.management.base import BaseCommand, CommandError |
|
36 |
|
|
37 |
from synnefo.db.models import Backend |
|
38 |
|
|
39 |
|
|
40 |
class Command(BaseCommand): |
|
41 |
args = "<backend ID>" |
|
42 |
help = "Modify a backend" |
|
43 |
|
|
44 |
option_list = BaseCommand.option_list + ( |
|
45 |
make_option('--clustername', |
|
46 |
dest='clustername', |
|
47 |
help="Set backend's clustername"), |
|
48 |
make_option('--port', |
|
49 |
dest='port', |
|
50 |
help="Set backend's port"), |
|
51 |
make_option('--username', |
|
52 |
dest='username', |
|
53 |
help="Set backend'username"), |
|
54 |
make_option('--password', |
|
55 |
dest='password', |
|
56 |
help="Set backend's password"), |
|
57 |
make_option('--drained', |
|
58 |
dest='drained', |
|
59 |
action='store_true', |
|
60 |
default=False, |
|
61 |
help="Set the backend as drained to exclude from allocation "\ |
|
62 |
"operations"), |
|
63 |
make_option('--no-drained', |
|
64 |
dest='drained', |
|
65 |
action='store_false'), |
|
66 |
make_option('--offline', |
|
67 |
dest='offline', |
|
68 |
action='store_true', |
|
69 |
default=False, |
|
70 |
help="Set the backend as offline to not communicate in order "\ |
|
71 |
"to avoid delays"), |
|
72 |
make_option('--no-offline', |
|
73 |
dest='offline', |
|
74 |
action='store_false') |
|
75 |
) |
|
76 |
|
|
77 |
def handle(self, *args, **options): |
|
78 |
if len(args) != 1: |
|
79 |
raise CommandError("Please provide a backend ID") |
|
80 |
|
|
81 |
try: |
|
82 |
backend_id = int(args[0]) |
|
83 |
backend = Backend.objects.get(id=backend_id) |
|
84 |
except ValueError: |
|
85 |
raise CommandError("Invalid backend ID") |
|
86 |
except Backend.DoesNotExist: |
|
87 |
raise CommandError("Backend not found in DB") |
|
88 |
|
|
89 |
# Ensure fields correspondence with options and Backend model |
|
90 |
fields = ('clustername', 'port', 'username', 'password', 'drained', |
|
91 |
'offline') |
|
92 |
for field in fields: |
|
93 |
value = options.get(field) |
|
94 |
if value is not None: |
|
95 |
backend.__setattr__(field, value) |
|
96 |
|
|
97 |
backend.save() |
/dev/null | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or without |
|
4 |
# modification, are permitted provided that the following conditions |
|
5 |
# are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above copyright |
|
8 |
# notice, this list of conditions and the following disclaimer. |
|
9 |
# |
|
10 |
# 2. Redistributions in binary form must reproduce the above copyright |
|
11 |
# notice, this list of conditions and the following disclaimer in the |
|
12 |
# documentation and/or other materials provided with the distribution. |
|
13 |
# |
|
14 |
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
15 |
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
16 |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
17 |
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
18 |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
19 |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
20 |
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
21 |
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
22 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
23 |
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
24 |
# SUCH DAMAGE. |
|
25 |
# |
|
26 |
# The views and conclusions contained in the software and documentation are |
|
27 |
# those of the authors and should not be interpreted as representing official |
|
28 |
# policies, either expressed or implied, of GRNET S.A. |
|
29 |
# |
|
30 |
|
|
31 |
from optparse import make_option |
|
32 |
from django.core.management.base import BaseCommand, CommandError |
|
33 |
from synnefo import settings |
|
34 |
import datetime |
|
35 |
|
|
36 |
from synnefo.db.models import Backend |
|
37 |
from synnefo.logic.backend import update_resources |
|
38 |
|
|
39 |
|
|
40 |
class Command(BaseCommand): |
|
41 |
can_import_settings = True |
|
42 |
|
|
43 |
help = "Update backend statistics, which are used for instance allocation." |
|
44 |
output_transaction = True # The management command runs inside |
|
45 |
# an SQL transaction |
|
46 |
option_list = BaseCommand.option_list + ( |
|
47 |
make_option('--backend_id', dest='backend_id', |
|
48 |
help="Update statistics of only this backend"), |
|
49 |
make_option('--older_than', dest='older_than', metavar="MINUTES", |
|
50 |
help="Update only backends that have not been updated for\ |
|
51 |
MINUTES. Set to 0 to force update.") |
|
52 |
) |
|
53 |
|
|
54 |
def handle(self, **options): |
|
55 |
|
|
56 |
if options['backend_id']: |
|
57 |
try: |
|
58 |
backend_id = int(options['backend_id']) |
|
59 |
backends = [Backend.objects.get(id=backend_id)] |
|
60 |
except ValueError: |
|
61 |
raise CommandError("Wrong backend ID") |
|
62 |
except Backend.DoesNotExist: |
|
63 |
raise CommandError("Backend not found in DB") |
|
64 |
else: |
|
65 |
# XXX:filter drained ? |
|
66 |
backends = Backend.objects.all() |
|
67 |
|
|
68 |
now = datetime.datetime.now() |
|
69 |
if options['older_than'] is not None: |
|
70 |
minutes = int(options['older_than']) |
|
71 |
else: |
|
72 |
minutes = settings.BACKEND_REFRESH_MIN |
|
73 |
|
|
74 |
delta = datetime.timedelta(minutes=minutes) |
|
75 |
|
|
76 |
for b in backends: |
|
77 |
if now > b.updated + delta: |
|
78 |
update_resources(b) |
|
79 |
print 'Successfully updated backend with id: %d' % b.id |
|
80 |
else: |
|
81 |
print 'Backend %d does not need update' % b.id |
b/snf-cyclades-app/synnefo/logic/management/commands/network-inspect.py | ||
---|---|---|
1 |
# Copyright 2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
import json |
|
35 |
|
|
36 |
from django.core.management.base import BaseCommand, CommandError |
|
37 |
|
|
38 |
from synnefo.db.models import Backend, Network, BackendNetwork |
|
39 |
from synnefo.util.rapi import GanetiApiError |
|
40 |
|
|
41 |
|
|
42 |
class Command(BaseCommand): |
|
43 |
help = "Inspect a network on DB and Ganeti." |
|
44 |
|
|
45 |
def handle(self, *args, **options): |
|
46 |
if len(args) != 1: |
|
47 |
raise CommandError("Please provide a network ID.") |
|
48 |
try: |
|
49 |
net_id = int(args[0]) |
|
50 |
except ValueError: |
|
51 |
raise CommandError("Invalid network ID.") |
|
52 |
|
|
53 |
try: |
|
54 |
net = Network.objects.get(id=net_id) |
|
55 |
except Network.DoesNotExist: |
|
56 |
raise CommandError("Network not found in DB.") |
|
57 |
|
|
58 |
sep = '-' * 80 + '\n' |
|
59 |
labels = ('name', 'backend-name', 'state', 'owner', 'subnet', 'gateway', |
|
60 |
'max_prefix', 'link', 'public', 'dhcp', 'type', 'deleted', |
|
61 |
'action') |
|
62 |
fields = (net.name, net.backend_id, net.state, str(net.userid), |
|
63 |
str(net.subnet), str(net.gateway), str(net.mac_prefix), |
|
64 |
str(net.link), str(net.public), str(net.dhcp), |
|
65 |
str(net.type), str(net.deleted), str(net.action)) |
|
66 |
|
|
67 |
self.stdout.write(sep) |
|
68 |
self.stdout.write('State of Network in DB\n') |
|
69 |
self.stdout.write(sep) |
|
70 |
for l, f in zip(labels, fields): |
|
71 |
self.stdout.write(l.ljust(20) + ': ' + f.ljust(20) + '\n') |
|
72 |
|
|
73 |
labels = ('Backend', 'State', 'Deleted', 'JobID', 'OpCode', |
|
74 |
'JobStatus') |
|
75 |
for back_net in BackendNetwork.objects.filter(network=net): |
|
76 |
self.stdout.write('\n') |
|
77 |
fields = (back_net.backend.clustername, back_net.operstate, |
|
78 |
str(back_net.deleted), str(back_net.backendjobid), |
|
79 |
str(back_net.backendopcode), |
|
80 |
str(back_net.backendjobstatus)) |
|
81 |
for l, f in zip(labels, fields): |
|
82 |
self.stdout.write(l.ljust(20) + ': ' + f.ljust(20) + '\n') |
|
83 |
self.stdout.write('\n') |
|
84 |
|
|
85 |
self.stdout.write(sep) |
|
86 |
self.stdout.write('State of Network in Ganeti\n') |
|
87 |
self.stdout.write(sep) |
|
88 |
|
|
89 |
for backend in Backend.objects.exclude(offline=True): |
|
90 |
client = backend.client |
|
91 |
try: |
|
92 |
g_net = client.GetNetwork(net.backend_id) |
|
93 |
self.stdout.write("Backend: %s\n" % backend.clustername) |
|
94 |
print json.dumps(g_net, indent=2) |
|
95 |
self.stdout.write(sep) |
|
96 |
except GanetiApiError as e: |
|
97 |
if e.code == 404: |
|
98 |
self.stdout.write('Network does not exist in backend %s\n' % |
|
99 |
backend.clustername) |
|
100 |
else: |
|
101 |
raise e |
/dev/null | ||
---|---|---|
1 |
# Copyright 2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
import json |
|
35 |
|
|
36 |
from django.core.management.base import BaseCommand, CommandError |
|
37 |
|
|
38 |
from synnefo.db.models import Backend, Network, BackendNetwork |
|
39 |
from synnefo.util.rapi import GanetiApiError |
|
40 |
|
|
41 |
|
|
42 |
class Command(BaseCommand): |
|
43 |
help = "Inspect a network on DB and Ganeti." |
|
44 |
|
|
45 |
def handle(self, *args, **options): |
|
46 |
if len(args) != 1: |
|
47 |
raise CommandError("Please provide a network ID.") |
|
48 |
try: |
|
49 |
net_id = int(args[0]) |
|
50 |
except ValueError: |
|
51 |
raise CommandError("Invalid network ID.") |
|
52 |
|
|
53 |
try: |
|
54 |
net = Network.objects.get(id=net_id) |
|
55 |
except Network.DoesNotExist: |
|
56 |
raise CommandError("Network not found in DB.") |
|
57 |
|
|
58 |
sep = '-' * 80 + '\n' |
|
59 |
labels = ('name', 'backend-name', 'state', 'owner', 'subnet', 'gateway', |
|
60 |
'max_prefix', 'link', 'public', 'dhcp', 'type', 'deleted', |
|
61 |
'action') |
|
62 |
fields = (net.name, net.backend_id, net.state, str(net.userid), |
|
63 |
str(net.subnet), str(net.gateway), str(net.mac_prefix), |
|
64 |
str(net.link), str(net.public), str(net.dhcp), |
|
65 |
str(net.type), str(net.deleted), str(net.action)) |
|
66 |
|
|
67 |
self.stdout.write(sep) |
|
68 |
self.stdout.write('State of Network in DB\n') |
|
69 |
self.stdout.write(sep) |
|
70 |
for l, f in zip(labels, fields): |
|
71 |
self.stdout.write(l.ljust(20) + ': ' + f.ljust(20) + '\n') |
|
72 |
|
|
73 |
labels = ('Backend', 'State', 'Deleted', 'JobID', 'OpCode', |
|
74 |
'JobStatus') |
|
75 |
for back_net in BackendNetwork.objects.filter(network=net): |
|
76 |
self.stdout.write('\n') |
|
77 |
fields = (back_net.backend.clustername, back_net.operstate, |
|
78 |
str(back_net.deleted), str(back_net.backendjobid), |
|
79 |
str(back_net.backendopcode), |
|
80 |
str(back_net.backendjobstatus)) |
|
81 |
for l, f in zip(labels, fields): |
|
82 |
self.stdout.write(l.ljust(20) + ': ' + f.ljust(20) + '\n') |
|
83 |
self.stdout.write('\n') |
|
84 |
|
|
85 |
self.stdout.write(sep) |
|
86 |
self.stdout.write('State of Network in Ganeti\n') |
|
87 |
self.stdout.write(sep) |
|
88 |
|
|
89 |
for backend in Backend.objects.exclude(offline=True): |
|
90 |
client = backend.client |
|
91 |
try: |
|
92 |
g_net = client.GetNetwork(net.backend_id) |
|
93 |
self.stdout.write("Backend: %s\n" % backend.clustername) |
|
94 |
print json.dumps(g_net, indent=2) |
|
95 |
self.stdout.write(sep) |
|
96 |
except GanetiApiError as e: |
|
97 |
if e.code == 404: |
|
98 |
self.stdout.write('Network does not exist in backend %s\n' % |
|
99 |
backend.clustername) |
|
100 |
else: |
|
101 |
raise e |
/dev/null | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or without |
|
4 |
# modification, are permitted provided that the following conditions |
|
5 |
# are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above copyright |
|
8 |
# notice, this list of conditions and the following disclaimer. |
|
9 |
# |
|
10 |
# 2. Redistributions in binary form must reproduce the above copyright |
|
11 |
# notice, this list of conditions and the following disclaimer in the |
|
12 |
# documentation and/or other materials provided with the distribution. |
|
13 |
# |
|
14 |
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
15 |
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
16 |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
17 |
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
18 |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
19 |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
20 |
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
21 |
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
22 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
23 |
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
24 |
# SUCH DAMAGE. |
|
25 |
# |
|
26 |
# The views and conclusions contained in the software and documentation are |
|
27 |
# those of the authors and should not be interpreted as representing official |
|
28 |
# policies, either expressed or implied, of GRNET S.A. |
|
29 |
# |
|
30 |
"""Reconciliation management command |
|
31 |
|
|
32 |
Management command to reconcile the contents of the Synnefo DB with |
|
33 |
the state of the Ganeti backend. See docstring on top of |
|
34 |
logic/reconciliation.py for a description of reconciliation rules. |
|
35 |
|
|
36 |
""" |
|
37 |
import datetime |
|
38 |
|
|
39 |
from optparse import make_option |
|
40 |
|
|
41 |
from django.conf import settings |
|
42 |
from django.core.management.base import BaseCommand, CommandError |
|
43 |
|
|
44 |
from synnefo.db.models import Backend, Network, BackendNetwork |
|
45 |
from synnefo.logic import reconciliation, backend, utils |
|
46 |
|
|
47 |
|
|
48 |
class Command(BaseCommand): |
|
49 |
can_import_settings = True |
|
50 |
|
|
51 |
help = 'Reconcile contents of Synnefo DB with state of Ganeti backend' |
|
52 |
output_transaction = True # The management command runs inside |
|
53 |
# an SQL transaction |
|
54 |
option_list = BaseCommand.option_list + ( |
|
55 |
make_option('--fix-all', action='store_true', |
|
56 |
dest='fix', default=False, |
|
57 |
help='Fix all issues.'), |
|
58 |
) |
|
59 |
|
|
60 |
def handle(self, **options): |
|
61 |
self.verbosity = int(options['verbosity']) |
|
62 |
fix = options['fix'] |
|
63 |
reconcile_networks(self.stdout, fix) |
|
64 |
|
|
65 |
|
|
66 |
def reconcile_networks(out, fix): |
|
67 |
# Get models from DB |
|
68 |
backends = Backend.objects.exclude(offline=True) |
|
69 |
networks = Network.objects.filter(deleted=False) |
|
70 |
|
|
71 |
# Get info from all ganeti backends |
|
72 |
ganeti_networks = {} |
|
73 |
ganeti_hanging_networks = {} |
|
74 |
for b in backends: |
|
75 |
g_nets = reconciliation.get_networks_from_ganeti(b) |
|
76 |
ganeti_networks[b] = g_nets |
|
77 |
g_hanging_nets = reconciliation.hanging_networks(b, g_nets) |
|
78 |
ganeti_hanging_networks[b] = g_hanging_nets |
|
79 |
|
|
80 |
# Perform reconciliation for each network |
|
81 |
for network in networks: |
|
82 |
net_id = network.id |
|
83 |
destroying = network.action == 'DESTROY' |
|
84 |
|
|
85 |
# Perform reconcilliation for each backend |
|
86 |
for b in backends: |
|
87 |
info = (net_id, b.clustername) |
|
88 |
back_network = None |
|
89 |
|
|
90 |
try: |
|
91 |
# Get the model describing the network to this backend |
|
92 |
back_network = BackendNetwork.objects.get(network=network, |
|
93 |
backend=b) |
|
94 |
except BackendNetwork.DoesNotExist: |
|
95 |
out.write('D: No DB entry for network %d in backend %s\n' % info) |
|
96 |
if fix: |
|
97 |
out.write('F: Created entry in DB\n') |
|
98 |
back_network = \ |
|
99 |
BackendNetwork.objects.create(network=network, |
|
100 |
backend=b) |
|
101 |
|
|
102 |
try: |
|
103 |
# Get the info from backend |
|
104 |
ganeti_networks[b][net_id] |
|
105 |
except KeyError: |
|
106 |
# Stale network does not exist in backend |
|
107 |
if destroying: |
|
108 |
out.write('D: Stale network %d in backend %s\n' % info) |
|
109 |
if fix: |
|
110 |
out.write("F: Issued OP_NETWORK_REMOVE'\n") |
|
111 |
etime = datetime.datetime.now() |
|
112 |
backend.process_network_status(back_network, etime, |
|
113 |
0, 'OP_NETWORK_REMOVE', 'success', |
|
114 |
'Reconciliation simulated event.') |
|
115 |
continue |
|
116 |
else: |
|
117 |
# Pending network |
|
118 |
out.write('D: Pending network %d in backend %s\n' % info) |
|
119 |
if fix: |
|
120 |
out.write('F: Creating network in backend.\n') |
|
121 |
backend.create_network(network, [b]) |
|
122 |
# Skip rest reconciliation as the network is just |
|
123 |
# being created |
|
124 |
continue |
|
125 |
|
|
126 |
try: |
|
127 |
hanging_groups = ganeti_hanging_networks[b][net_id] |
|
128 |
except KeyError: |
|
129 |
# Network is connected to all nodegroups |
|
130 |
hanging_groups = [] |
|
131 |
|
|
132 |
if hanging_groups and not destroying: |
|
133 |
# Hanging network = not connected to all nodegroups of backend |
|
134 |
out.write('D: Network %d in backend %s is not connected to ' |
|
135 |
'the following groups:\n' % info) |
|
136 |
out.write('- ' + '\n- '.join(hanging_groups) + '\n') |
|
137 |
if fix: |
|
138 |
for group in hanging_groups: |
|
139 |
out.write('F: Connecting network %d to nodegroup %s\n' |
|
140 |
% (net_id, group)) |
|
141 |
backend.connect_network_group(b, network, group) |
|
142 |
elif back_network and back_network.operstate != 'ACTIVE': |
|
143 |
# Network is active |
|
144 |
out.write('D: Unsynced network %d in backend %s\n' % info) |
|
145 |
if fix: |
|
146 |
out.write("F: Issued OP_NETWORK_CONNECT\n") |
|
147 |
etime = datetime.datetime.now() |
|
148 |
backend.process_network_status(back_network, etime, |
|
149 |
0, 'OP_NETWORK_CONNECT', 'success', |
|
150 |
'Reconciliation simulated event.') |
|
151 |
|
|
152 |
# Detect Orphan Networks in Ganeti |
|
153 |
db_network_ids = set([net.id for net in networks]) |
|
154 |
for back_end, ganeti_networks in ganeti_networks.items(): |
|
155 |
ganeti_network_ids = set(ganeti_networks.keys()) |
|
156 |
orphans = ganeti_network_ids - db_network_ids |
|
157 |
|
|
158 |
if len(orphans) > 0: |
|
159 |
out.write('D: Orphan Networks in backend %s:\n' % back_end.clustername) |
|
160 |
out.write('- ' + '\n- '.join([str(o) for o in orphans]) + '\n') |
|
161 |
client = back_end.client |
|
162 |
if fix: |
|
163 |
#XXX:Move this to backend |
|
164 |
for id in orphans: |
|
165 |
out.write('Disconnecting and deleting network %d\n' % id) |
|
166 |
network = utils.id_to_network_name(id) |
|
167 |
for group in client.GetGroups(): |
|
168 |
client.DisconnectNetwork(network, group) |
|
169 |
client.DeleteNetwork(network) |
b/snf-cyclades-app/synnefo/logic/management/commands/reconcile-networks.py | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or without |
|
4 |
# modification, are permitted provided that the following conditions |
|
5 |
# are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above copyright |
|
8 |
# notice, this list of conditions and the following disclaimer. |
|
9 |
# |
|
10 |
# 2. Redistributions in binary form must reproduce the above copyright |
|
11 |
# notice, this list of conditions and the following disclaimer in the |
|
12 |
# documentation and/or other materials provided with the distribution. |
|
13 |
# |
|
14 |
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
15 |
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
16 |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
17 |
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
18 |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
19 |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
20 |
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
21 |
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
22 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
23 |
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
24 |
# SUCH DAMAGE. |
|
25 |
# |
|
26 |
# The views and conclusions contained in the software and documentation are |
|
27 |
# those of the authors and should not be interpreted as representing official |
|
28 |
# policies, either expressed or implied, of GRNET S.A. |
|
29 |
# |
|
30 |
"""Reconciliation management command |
|
31 |
|
|
32 |
Management command to reconcile the contents of the Synnefo DB with |
|
33 |
the state of the Ganeti backend. See docstring on top of |
|
34 |
logic/reconciliation.py for a description of reconciliation rules. |
|
35 |
|
|
36 |
""" |
|
37 |
import datetime |
|
38 |
|
|
39 |
from optparse import make_option |
|
40 |
|
|
41 |
from django.conf import settings |
|
42 |
from django.core.management.base import BaseCommand, CommandError |
|
43 |
|
|
44 |
from synnefo.db.models import Backend, Network, BackendNetwork |
|
45 |
from synnefo.logic import reconciliation, backend, utils |
|
46 |
|
|
47 |
|
|
48 |
class Command(BaseCommand): |
|
49 |
can_import_settings = True |
|
50 |
|
|
51 |
help = 'Reconcile contents of Synnefo DB with state of Ganeti backend' |
|
52 |
output_transaction = True # The management command runs inside |
|
53 |
# an SQL transaction |
|
54 |
option_list = BaseCommand.option_list + ( |
|
55 |
make_option('--fix-all', action='store_true', |
|
56 |
dest='fix', default=False, |
|
57 |
help='Fix all issues.'), |
|
58 |
) |
|
59 |
|
|
60 |
def handle(self, **options): |
|
61 |
self.verbosity = int(options['verbosity']) |
|
62 |
fix = options['fix'] |
|
63 |
reconcile_networks(self.stdout, fix) |
|
64 |
|
|
65 |
|
|
66 |
def reconcile_networks(out, fix): |
|
67 |
# Get models from DB |
|
68 |
backends = Backend.objects.exclude(offline=True) |
|
69 |
networks = Network.objects.filter(deleted=False) |
|
70 |
|
|
71 |
# Get info from all ganeti backends |
|
72 |
ganeti_networks = {} |
|
73 |
ganeti_hanging_networks = {} |
|
74 |
for b in backends: |
|
75 |
g_nets = reconciliation.get_networks_from_ganeti(b) |
|
76 |
ganeti_networks[b] = g_nets |
|
77 |
g_hanging_nets = reconciliation.hanging_networks(b, g_nets) |
|
78 |
ganeti_hanging_networks[b] = g_hanging_nets |
|
79 |
|
|
80 |
# Perform reconciliation for each network |
|
81 |
for network in networks: |
|
82 |
net_id = network.id |
|
83 |
destroying = network.action == 'DESTROY' |
|
84 |
|
|
85 |
# Perform reconcilliation for each backend |
|
86 |
for b in backends: |
|
87 |
info = (net_id, b.clustername) |
|
88 |
back_network = None |
|
89 |
|
|
90 |
try: |
|
91 |
# Get the model describing the network to this backend |
|
92 |
back_network = BackendNetwork.objects.get(network=network, |
|
93 |
backend=b) |
|
94 |
except BackendNetwork.DoesNotExist: |
|
95 |
out.write('D: No DB entry for network %d in backend %s\n' % info) |
|
96 |
if fix: |
|
97 |
out.write('F: Created entry in DB\n') |
|
98 |
back_network = \ |
|
99 |
BackendNetwork.objects.create(network=network, |
|
100 |
backend=b) |
|
101 |
|
|
102 |
try: |
|
103 |
# Get the info from backend |
|
104 |
ganeti_networks[b][net_id] |
|
105 |
except KeyError: |
|
106 |
# Stale network does not exist in backend |
|
107 |
if destroying: |
|
108 |
out.write('D: Stale network %d in backend %s\n' % info) |
|
109 |
if fix: |
|
110 |
out.write("F: Issued OP_NETWORK_REMOVE'\n") |
|
111 |
etime = datetime.datetime.now() |
|
112 |
backend.process_network_status(back_network, etime, |
|
113 |
0, 'OP_NETWORK_REMOVE', 'success', |
|
114 |
'Reconciliation simulated event.') |
|
115 |
continue |
|
116 |
else: |
|
117 |
# Pending network |
|
118 |
out.write('D: Pending network %d in backend %s\n' % info) |
|
119 |
if fix: |
|
120 |
out.write('F: Creating network in backend.\n') |
|
121 |
backend.create_network(network, [b]) |
|
122 |
# Skip rest reconciliation as the network is just |
|
123 |
# being created |
|
124 |
continue |
|
125 |
|
|
126 |
try: |
|
127 |
hanging_groups = ganeti_hanging_networks[b][net_id] |
|
128 |
except KeyError: |
|
129 |
# Network is connected to all nodegroups |
|
130 |
hanging_groups = [] |
|
131 |
|
|
132 |
if hanging_groups and not destroying: |
|
133 |
# Hanging network = not connected to all nodegroups of backend |
|
134 |
out.write('D: Network %d in backend %s is not connected to ' |
|
135 |
'the following groups:\n' % info) |
|
136 |
out.write('- ' + '\n- '.join(hanging_groups) + '\n') |
|
137 |
if fix: |
|
138 |
for group in hanging_groups: |
|
139 |
out.write('F: Connecting network %d to nodegroup %s\n' |
|
140 |
% (net_id, group)) |
|
141 |
backend.connect_network_group(b, network, group) |
|
142 |
elif back_network and back_network.operstate != 'ACTIVE': |
|
143 |
# Network is active |
|
144 |
out.write('D: Unsynced network %d in backend %s\n' % info) |
|
145 |
if fix: |
|
146 |
out.write("F: Issued OP_NETWORK_CONNECT\n") |
|
147 |
etime = datetime.datetime.now() |
|
148 |
backend.process_network_status(back_network, etime, |
|
149 |
0, 'OP_NETWORK_CONNECT', 'success', |
|
150 |
'Reconciliation simulated event.') |
|
151 |
|
|
152 |
# Detect Orphan Networks in Ganeti |
|
153 |
db_network_ids = set([net.id for net in networks]) |
|
154 |
for back_end, ganeti_networks in ganeti_networks.items(): |
|
155 |
ganeti_network_ids = set(ganeti_networks.keys()) |
|
156 |
orphans = ganeti_network_ids - db_network_ids |
|
157 |
|
|
158 |
if len(orphans) > 0: |
|
159 |
out.write('D: Orphan Networks in backend %s:\n' % back_end.clustername) |
|
160 |
out.write('- ' + '\n- '.join([str(o) for o in orphans]) + '\n') |
|
161 |
client = back_end.client |
|
162 |
if fix: |
|
163 |
#XXX:Move this to backend |
|
164 |
for id in orphans: |
|
165 |
out.write('Disconnecting and deleting network %d\n' % id) |
|
166 |
network = utils.id_to_network_name(id) |
|
167 |
for group in client.GetGroups(): |
|
168 |
client.DisconnectNetwork(network, group) |
|
169 |
client.DeleteNetwork(network) |
b/snf-cyclades-app/synnefo/logic/management/commands/server-inspect.py | ||
---|---|---|
1 |
# Copyright 2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
|
|
35 |
from datetime import datetime |
|
36 |
from optparse import make_option |
|
37 |
from django.core.management.base import BaseCommand, CommandError |
|
38 |
|
|
39 |
from synnefo.api.util import get_image |
|
40 |
from synnefo.lib.utils import merge_time |
|
41 |
from synnefo.db.models import VirtualMachine |
|
42 |
from synnefo.util.rapi import GanetiApiError |
|
43 |
|
|
44 |
|
|
45 |
# Fields to print from a gnt-instance info |
|
46 |
GANETI_INSTANCE_FIELDS = ('name', 'oper_state', 'admin_state', 'status', |
|
47 |
'pnode', 'snode', 'network_port', 'disk_template', |
|
48 |
'disk_usage', 'oper_ram', 'oper_vcpus', 'mtime', |
|
49 |
'nic.ips', 'nic.macs', 'nic.networks', 'nic.modes') |
|
50 |
|
|
51 |
# Fields to print from a gnt-job info |
|
52 |
GANETI_JOB_FIELDS = ('id', 'status', 'summary', 'opresult', 'opstatus', |
|
53 |
'oplog', 'start_ts', 'end_ts') |
|
54 |
|
|
55 |
|
|
56 |
class Command(BaseCommand): |
|
57 |
help = "Inspect a server on DB and Ganeti" |
|
58 |
|
|
59 |
option_list = BaseCommand.option_list + ( |
|
60 |
make_option('--jobs', action='store_true', |
|
61 |
dest='jobs', default='False', |
|
62 |
help="Show non-archived jobs concerning server." |
|
63 |
), |
|
64 |
) |
|
65 |
|
|
66 |
def handle(self, *args, **options): |
|
67 |
if len(args) != 1: |
|
68 |
raise CommandError("Please provide a server ID") |
|
69 |
|
|
70 |
try: |
|
71 |
vm_id = int(args[0]) |
|
72 |
except ValueError: |
|
73 |
raise CommandError("Invalid server ID") |
|
74 |
|
|
75 |
try: |
|
76 |
vm = VirtualMachine.objects.get(id=vm_id) |
|
77 |
except VirtualMachine.DoesNotExist: |
|
78 |
raise CommandError("Server not found in DB") |
|
79 |
|
|
80 |
try: |
|
81 |
image = get_image(vm.imageid, vm.userid)['name'] |
|
82 |
except: |
|
83 |
image = vm.imageid |
Also available in: Unified diff