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
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff