Revision 475d4a85
/dev/null | ||
---|---|---|
1 |
# Copyright 2012, 2013 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 itertools |
|
35 |
import warnings |
|
36 |
import functools |
|
37 |
|
|
38 |
from optparse import make_option |
|
39 |
|
|
40 |
from django.core.management.base import NoArgsCommand, CommandError, BaseCommand |
|
41 |
from django.db import transaction |
|
42 |
from django.conf import settings |
|
43 |
|
|
44 |
from synnefo.api.util import get_existing_users |
|
45 |
from synnefo.lib.utils import case_unique |
|
46 |
from synnefo.db.models import Network, VirtualMachine |
|
47 |
from synnefo.userdata.models import PublicKeyPair |
|
48 |
|
|
49 |
from snf_django.lib import astakos |
|
50 |
|
|
51 |
def warn(*msgs): |
|
52 |
print "WARNING: %s" % ' '.join(msgs) |
|
53 |
|
|
54 |
get_displayname = functools.partial(astakos.get_displayname, |
|
55 |
settings.CYCLADES_SERVICE_TOKEN, |
|
56 |
url=settings.ASTAKOS_URL.replace('im/authenticate', |
|
57 |
'service/api/user_catalogs')) |
|
58 |
get_user_uuid = functools.partial(astakos.get_user_uuid, |
|
59 |
settings.CYCLADES_SERVICE_TOKEN, |
|
60 |
url=settings.ASTAKOS_URL.replace('im/authenticate', |
|
61 |
'service/api/user_catalogs')) |
|
62 |
|
|
63 |
def _validate_db_state(usernames): |
|
64 |
|
|
65 |
usernames = filter(bool, usernames) |
|
66 |
invalid_case_users = case_unique(usernames) |
|
67 |
if invalid_case_users: |
|
68 |
invalid_case_users.append(invalid_case_users[0].lower()) |
|
69 |
raise CommandError("Duplicate case insensitive user identifiers exist %r" % invalid_case_users) |
|
70 |
|
|
71 |
uuidusers = filter(lambda uid:'@' in uid or uid == None, usernames) |
|
72 |
if len(uuidusers) != len(usernames): |
|
73 |
warn('It seems that mixed uuid/email user identifiers exist in database.') |
|
74 |
return False |
|
75 |
|
|
76 |
return True |
|
77 |
|
|
78 |
|
|
79 |
@transaction.commit_manually |
|
80 |
def delete_user(username, only_stats=True, dry=True): |
|
81 |
vms = VirtualMachine.objects.filter(userid__exact=username) |
|
82 |
networks = Network.objects.filter(userid__exact=username) |
|
83 |
keys = PublicKeyPair.objects.filter(user__exact=username) |
|
84 |
|
|
85 |
if not len(list(itertools.ifilter(bool, map(lambda q: q.count(), [vms, |
|
86 |
networks, |
|
87 |
keys])))): |
|
88 |
print "No entries exist for '%s'" % username |
|
89 |
return -1 |
|
90 |
|
|
91 |
if only_stats: |
|
92 |
print "The following entries will be deleted if you decide to remove this user" |
|
93 |
print "%d Virtual Machines" % vms.exclude(operstate='DESTROYED').count() |
|
94 |
print "%d Destroyed Virtual Machines" % vms.filter(operstate='DESTROYED').count() |
|
95 |
print "%d Networks" % networks.count() |
|
96 |
print "%d PublicKeyPairs" % keys.count() |
|
97 |
return |
|
98 |
|
|
99 |
for o in itertools.chain(vms, networks): |
|
100 |
o.delete() |
|
101 |
|
|
102 |
for key in keys: |
|
103 |
key.delete() |
|
104 |
|
|
105 |
if dry: |
|
106 |
print "Skipping database commit." |
|
107 |
transaction.rollback() |
|
108 |
else: |
|
109 |
transaction.commit() |
|
110 |
print "User entries removed." |
|
111 |
|
|
112 |
|
|
113 |
@transaction.commit_on_success |
|
114 |
def merge_user(username): |
|
115 |
vms = VirtualMachine.objects.filter(userid__iexact=username) |
|
116 |
networks = Network.objects.filter(userid__iexact=username) |
|
117 |
keys = PublicKeyPair.objects.filter(user__iexact=username) |
|
118 |
|
|
119 |
for o in itertools.chain(vms, networks): |
|
120 |
o.userid = username.lower() |
|
121 |
o.save() |
|
122 |
|
|
123 |
for key in keys: |
|
124 |
key.user = username.lower() |
|
125 |
key.save() |
|
126 |
|
|
127 |
|
|
128 |
def migrate_user(username, uuid): |
|
129 |
""" |
|
130 |
Warn: no transaction handling. Consider wrapping within another function. |
|
131 |
""" |
|
132 |
vms = VirtualMachine.objects.filter(userid__exact=username) |
|
133 |
networks = Network.objects.filter(userid__exact=username) |
|
134 |
keys = PublicKeyPair.objects.filter(user__exact=username) |
|
135 |
|
|
136 |
for o in itertools.chain(vms, networks): |
|
137 |
o.userid = uuid or o.userid |
|
138 |
o.save() |
|
139 |
|
|
140 |
for key in keys: |
|
141 |
key.user = uuid |
|
142 |
key.save() |
|
143 |
|
|
144 |
|
|
145 |
@transaction.commit_manually |
|
146 |
def migrate_users(usernames, dry=True): |
|
147 |
usernames = filter(bool, usernames) |
|
148 |
count = 0 |
|
149 |
for u in usernames: |
|
150 |
if not '@' in u: |
|
151 |
warn('Skipping %s. It doesn\'t seem to be an email' % u) |
|
152 |
continue |
|
153 |
|
|
154 |
try: |
|
155 |
uuid = get_user_uuid(u) |
|
156 |
print "%s -> %s" % (u, uuid) |
|
157 |
if not uuid: |
|
158 |
raise Exception("No uuid for %s" % u) |
|
159 |
migrate_user(u, uuid) |
|
160 |
count += 1 |
|
161 |
except Exception, e: |
|
162 |
print "ERROR: User id migration failed (%s)" % e |
|
163 |
|
|
164 |
if dry: |
|
165 |
print "Skipping database commit." |
|
166 |
transaction.rollback() |
|
167 |
else: |
|
168 |
transaction.commit() |
|
169 |
print "Migrated %d users" % count |
|
170 |
|
|
171 |
|
|
172 |
class Command(NoArgsCommand): |
|
173 |
help = "Quotas migration helper" |
|
174 |
|
|
175 |
option_list = BaseCommand.option_list + ( |
|
176 |
make_option('--strict', |
|
177 |
dest='strict', |
|
178 |
action="store_false", |
|
179 |
default=True, |
|
180 |
help="Exit on warnings."), |
|
181 |
make_option('--validate-db', |
|
182 |
dest='validate', |
|
183 |
action="store_true", |
|
184 |
default=True, |
|
185 |
help=("Check if cyclades database contents are valid for " |
|
186 |
"migration.")), |
|
187 |
make_option('--migrate-users', |
|
188 |
dest='migrate_users', |
|
189 |
action="store_true", |
|
190 |
default=False, |
|
191 |
help=("Convert emails to uuids for all users stored in " |
|
192 |
"database.")), |
|
193 |
make_option('--merge-user', |
|
194 |
dest='merge_user', |
|
195 |
default=False, |
|
196 |
help="Merge case insensitive duplicates of a user."), |
|
197 |
make_option('--delete-user', |
|
198 |
dest='delete_user', |
|
199 |
action='store', |
|
200 |
default=False, |
|
201 |
help="Delete user entries."), |
|
202 |
make_option('--user-entries', |
|
203 |
dest='user_entries', |
|
204 |
action='store', |
|
205 |
default=False, |
|
206 |
help="Display user summary."), |
|
207 |
make_option('--dry', |
|
208 |
dest='dry', |
|
209 |
action="store_true", |
|
210 |
default=False, |
|
211 |
help="Do not commit database changes. Do not communicate " |
|
212 |
"with quotaholder"), |
|
213 |
make_option('--user', |
|
214 |
dest='user', |
|
215 |
action="store", |
|
216 |
default=False,) |
|
217 |
) |
|
218 |
|
|
219 |
def resolve_conflicts(self, options): |
|
220 |
conflicting = map(options.get, ['migrate_users', |
|
221 |
'merge_user']) |
|
222 |
if len(filter(bool, conflicting)) > 1: |
|
223 |
raise CommandError('You can use only one of --validate,' |
|
224 |
'--migrate-users') |
|
225 |
|
|
226 |
def handle(self, *args, **options): |
|
227 |
self.resolve_conflicts(options) |
|
228 |
self.strict = options.get('strict') |
|
229 |
self.dry = options.get('dry') |
|
230 |
|
|
231 |
if options.get('validate') and not options.get('merge_user') and not \ |
|
232 |
options.get('delete_user') and not options.get('user_entries'): |
|
233 |
usernames = get_existing_users() |
|
234 |
_validate_db_state(usernames) |
|
235 |
|
|
236 |
if options.get('migrate_users'): |
|
237 |
migrate_users(usernames, dry=self.dry) |
|
238 |
|
|
239 |
if options.get('merge_user'): |
|
240 |
merge_user(options.get('merge_user')) |
|
241 |
print "Merge finished." |
|
242 |
|
|
243 |
if options.get('delete_user'): |
|
244 |
entries = delete_user(options.get('delete_user'), only_stats=True) |
|
245 |
if entries == -1: |
|
246 |
return |
|
247 |
|
|
248 |
confirm = raw_input("Type 'yes of course' if you are sure you want" |
|
249 |
" to remove those entries: ") |
|
250 |
if not confirm == 'yes of course': |
|
251 |
return |
|
252 |
else: |
|
253 |
delete_user(options.get('delete_user'), only_stats=False, |
|
254 |
dry=self.dry) |
|
255 |
|
|
256 |
if options.get('user_entries'): |
|
257 |
delete_user(options.get('user_entries')) |
/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 itertools import product |
|
35 |
from optparse import make_option |
|
36 |
|
|
37 |
from django.core.management.base import BaseCommand, CommandError |
|
38 |
|
|
39 |
from synnefo.db.models import Flavor |
|
40 |
|
|
41 |
|
|
42 |
class Command(BaseCommand): |
|
43 |
output_transaction = True |
|
44 |
|
|
45 |
option_list = BaseCommand.option_list + ( |
|
46 |
make_option("-n", "--dry-run", dest="dry_run", action="store_true"), |
|
47 |
) |
|
48 |
args = "<cpu>[,<cpu>,...] " \ |
|
49 |
"<ram>[,<ram>,...] " \ |
|
50 |
"<disk>[,<disk>,...] " \ |
|
51 |
"<disk template>[,<disk template>,...]" |
|
52 |
help = "Create one or more flavors.\n\nThe flavors that will be created"\ |
|
53 |
" are those belonging to the cartesian product of the arguments" |
|
54 |
|
|
55 |
def handle(self, *args, **options): |
|
56 |
if len(args) != 4: |
|
57 |
raise CommandError("Invalid number of arguments") |
|
58 |
|
|
59 |
cpus = args[0].split(',') |
|
60 |
rams = args[1].split(',') |
|
61 |
disks = args[2].split(',') |
|
62 |
templates = args[3].split(',') |
|
63 |
|
|
64 |
flavors = [] |
|
65 |
for cpu, ram, disk, template in product(cpus, rams, disks, templates): |
|
66 |
try: |
|
67 |
flavors.append((int(cpu), int(ram), int(disk), template)) |
|
68 |
except ValueError: |
|
69 |
raise CommandError("Invalid values") |
|
70 |
|
|
71 |
for cpu, ram, disk, template in flavors: |
|
72 |
if options["dry_run"]: |
|
73 |
flavor = Flavor(cpu=cpu, ram=ram, disk=disk, |
|
74 |
disk_template=template) |
|
75 |
self.stdout.write("Creating flavor '%s'\n" % (flavor.name,)) |
|
76 |
else: |
|
77 |
flavor, created = \ |
|
78 |
Flavor.objects.get_or_create(cpu=cpu, ram=ram, disk=disk, |
|
79 |
disk_template=template) |
|
80 |
if created: |
|
81 |
self.stdout.write("Created flavor '%s'\n" % (flavor.name,)) |
|
82 |
else: |
|
83 |
self.stdout.write("Flavor '%s' already exists\n" |
|
84 |
% flavor.name) |
|
85 |
if flavor.deleted: |
|
86 |
msg = "Flavor '%s' is marked as deleted. Use"\ |
|
87 |
" 'snf-manage flavor-modify' to restore this flavor\n"\ |
|
88 |
% flavor.name |
|
89 |
self.stdout.write(msg) |
/dev/null | ||
---|---|---|
1 |
# Copyright 2012-2013 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 snf_django.management.commands import ListCommand |
|
35 |
from synnefo.db.models import Flavor, VirtualMachine |
|
36 |
|
|
37 |
|
|
38 |
class Command(ListCommand): |
|
39 |
help = "List available server flavors" |
|
40 |
|
|
41 |
object_class = Flavor |
|
42 |
deleted_field = "deleted" |
|
43 |
|
|
44 |
def get_vms(flavor): |
|
45 |
return VirtualMachine.objects.filter(flavor=flavor, deleted=False)\ |
|
46 |
.count() |
|
47 |
|
|
48 |
FIELDS = { |
|
49 |
"id": ("id", "Flavor's unique ID"), |
|
50 |
"name": ("name", "Flavor's unique name"), |
|
51 |
"cpu": ("cpu", "Number of CPUs"), |
|
52 |
"ram": ("ram", "Size(MB) of RAM"), |
|
53 |
"disk": ("disk", "Size(GB) of disk"), |
|
54 |
"template": ("disk_template", "Disk template"), |
|
55 |
"vms": (get_vms, "Number of active servers using this flavor") |
|
56 |
} |
|
57 |
|
|
58 |
fields = ["id", "name", "cpu", "ram", "disk", "template", "vms"] |
/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 |
|
|
36 |
from django.core.management.base import BaseCommand, CommandError |
|
37 |
from synnefo.management.common import get_flavor |
|
38 |
from snf_django.management.utils import parse_bool |
|
39 |
|
|
40 |
|
|
41 |
from logging import getLogger |
|
42 |
log = getLogger(__name__) |
|
43 |
|
|
44 |
|
|
45 |
class Command(BaseCommand): |
|
46 |
args = "<flavor id>" |
|
47 |
help = "Modify a flavor" |
|
48 |
|
|
49 |
option_list = BaseCommand.option_list + ( |
|
50 |
make_option( |
|
51 |
"--deleted", |
|
52 |
dest="deleted", |
|
53 |
metavar="True|False", |
|
54 |
choices=["True", "False"], |
|
55 |
default=None, |
|
56 |
help="Mark/unmark a flavor as deleted"), |
|
57 |
) |
|
58 |
|
|
59 |
def handle(self, *args, **options): |
|
60 |
if len(args) != 1: |
|
61 |
raise CommandError("Please provide a flavor ID") |
|
62 |
|
|
63 |
flavor = get_flavor(args[0]) |
|
64 |
|
|
65 |
deleted = options['deleted'] |
|
66 |
if deleted: |
|
67 |
deleted = parse_bool(deleted) |
|
68 |
log.info("Marking flavor %s as deleted=%s", flavor, deleted) |
|
69 |
flavor.deleted = deleted |
|
70 |
flavor.save() |
|
71 |
else: |
|
72 |
log.info("Nothing changed!") |
/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 |
|
|
36 |
from django.core.management.base import BaseCommand, CommandError |
|
37 |
from synnefo.management import common |
|
38 |
from synnefo.logic import servers |
|
39 |
|
|
40 |
|
|
41 |
class Command(BaseCommand): |
|
42 |
help = "Attach a floating IP to a VM or router" |
|
43 |
|
|
44 |
option_list = BaseCommand.option_list + ( |
|
45 |
make_option( |
|
46 |
'--machine', |
|
47 |
dest='machine', |
|
48 |
default=None, |
|
49 |
help='The server id the floating-ip will be attached to'), |
|
50 |
) |
|
51 |
|
|
52 |
@common.convert_api_faults |
|
53 |
def handle(self, *args, **options): |
|
54 |
if not args or len(args) > 1: |
|
55 |
raise CommandError("Command accepts exactly one argument") |
|
56 |
|
|
57 |
floating_ip_id = args[0] # this is the floating-ip address |
|
58 |
device = options['machine'] |
|
59 |
|
|
60 |
if not device: |
|
61 |
raise CommandError('Please give either a server or a router id') |
|
62 |
|
|
63 |
#get the vm |
|
64 |
vm = common.get_vm(device) |
|
65 |
floating_ip = common.get_floating_ip_by_id(floating_ip_id, |
|
66 |
for_update=True) |
|
67 |
servers.create_port(vm.userid, floating_ip.network, |
|
68 |
use_ipaddress=floating_ip, machine=vm) |
|
69 |
|
|
70 |
self.stdout.write("Attached %s to %s.\n" % (floating_ip, vm)) |
/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 |
|
|
36 |
from django.core.management.base import BaseCommand, CommandError |
|
37 |
from synnefo.management.common import convert_api_faults |
|
38 |
from synnefo.logic import ips |
|
39 |
from synnefo.api import util |
|
40 |
|
|
41 |
|
|
42 |
class Command(BaseCommand): |
|
43 |
help = "Allocate a new floating IP" |
|
44 |
|
|
45 |
option_list = BaseCommand.option_list + ( |
|
46 |
make_option( |
|
47 |
'--pool', |
|
48 |
dest='pool', |
|
49 |
help="The ID of the floating IP pool(network) to allocate the" |
|
50 |
" address from"), |
|
51 |
make_option( |
|
52 |
'--address', |
|
53 |
dest='address', |
|
54 |
help="The address to be allocated"), |
|
55 |
make_option( |
|
56 |
'--owner', |
|
57 |
dest='owner', |
|
58 |
default=None, |
|
59 |
help='The owner of the floating IP'), |
|
60 |
) |
|
61 |
|
|
62 |
@convert_api_faults |
|
63 |
def handle(self, *args, **options): |
|
64 |
if args: |
|
65 |
raise CommandError("Command doesn't accept any arguments") |
|
66 |
|
|
67 |
network_id = options['pool'] |
|
68 |
address = options['address'] |
|
69 |
owner = options['owner'] |
|
70 |
|
|
71 |
if not owner: |
|
72 |
raise CommandError("'owner' is required for floating IP creation") |
|
73 |
|
|
74 |
if network_id is not None: |
|
75 |
network = util.get_network(network_id, owner, for_update=True, |
|
76 |
non_deleted=True) |
|
77 |
else: |
|
78 |
network = None |
|
79 |
|
|
80 |
floating_ip = ips.create_floating_ip(userid=owner, |
|
81 |
network=network, |
|
82 |
address=address) |
|
83 |
|
|
84 |
self.stdout.write("Created floating IP '%s'.\n" % floating_ip) |
/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 |
|
|
36 |
from django.core.management.base import BaseCommand, CommandError |
|
37 |
from synnefo.management import common |
|
38 |
from synnefo.logic import servers |
|
39 |
|
|
40 |
|
|
41 |
class Command(BaseCommand): |
|
42 |
help = "Dettach a floating IP from a VM or router" |
|
43 |
|
|
44 |
@common.convert_api_faults |
|
45 |
def handle(self, *args, **options): |
|
46 |
if not args or len(args) > 1: |
|
47 |
raise CommandError("Command accepts exactly one argument") |
|
48 |
|
|
49 |
floating_ip_id = args[0] |
|
50 |
|
|
51 |
#get the floating-ip |
|
52 |
floating_ip = common.get_floating_ip_by_id(floating_ip_id, |
|
53 |
for_update=True) |
|
54 |
|
|
55 |
if not floating_ip.nic: |
|
56 |
raise CommandError('This floating IP is not attached to a device') |
|
57 |
|
|
58 |
nic = floating_ip.nic |
|
59 |
vm = nic.machine |
|
60 |
servers.delete_port(nic) |
|
61 |
self.stdout.write("Dettached floating IP %s from %s.\n" |
|
62 |
% (floating_ip_id, vm)) |
/dev/null | ||
---|---|---|
1 |
# Copyright 2013 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 |
|
|
36 |
from django.db import transaction |
|
37 |
from django.core.management.base import CommandError |
|
38 |
from snf_django.management.commands import RemoveCommand |
|
39 |
from synnefo.management import common |
|
40 |
from synnefo.logic import ips |
|
41 |
|
|
42 |
|
|
43 |
class Command(RemoveCommand): |
|
44 |
args = "<Floating-IP ID> [<Floating-IP ID> ...]" |
|
45 |
help = "Release a floating IP" |
|
46 |
|
|
47 |
@common.convert_api_faults |
|
48 |
@transaction.commit_on_success |
|
49 |
def handle(self, *args, **options): |
|
50 |
if not args: |
|
51 |
raise CommandError("Please provide a floating-ip ID") |
|
52 |
|
|
53 |
force = options['force'] |
|
54 |
message = "floating IPs" if len(args) > 1 else "floating IP" |
|
55 |
self.confirm_deletion(force, message, args) |
|
56 |
|
|
57 |
for floating_ip_id in args: |
|
58 |
self.stdout.write("\n") |
|
59 |
try: |
|
60 |
floating_ip = common.get_floating_ip_by_id(floating_ip_id, |
|
61 |
for_update=True) |
|
62 |
ips.delete_floating_ip(floating_ip) |
|
63 |
self.stdout.write("Deleted floating IP '%s'.\n" % |
|
64 |
floating_ip_id) |
|
65 |
except CommandError as e: |
|
66 |
self.stdout.write("Error -- %s\n" % e.message) |
/dev/null | ||
---|---|---|
1 |
# Copyright 2013 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 snf_django.management.commands import ListCommand |
|
36 |
from synnefo.db.models import IPAddressLog |
|
37 |
from optparse import make_option |
|
38 |
|
|
39 |
from logging import getLogger |
|
40 |
log = getLogger(__name__) |
|
41 |
|
|
42 |
|
|
43 |
class Command(ListCommand): |
|
44 |
help = "Information about a floating IP" |
|
45 |
|
|
46 |
option_list = ListCommand.option_list + ( |
|
47 |
make_option( |
|
48 |
'--address', |
|
49 |
dest='address', |
|
50 |
help="Display IP history only for this address"), |
|
51 |
make_option( |
|
52 |
'--server', |
|
53 |
dest='server', |
|
54 |
help="Display IP history only for this server"), |
|
55 |
make_option( |
|
56 |
'--active', |
|
57 |
dest="active", |
|
58 |
action="store_true", |
|
59 |
default=False, |
|
60 |
help="Display only IPs that are currently in use") |
|
61 |
) |
|
62 |
|
|
63 |
object_class = IPAddressLog |
|
64 |
order_by = "allocated_at" |
|
65 |
|
|
66 |
FIELDS = { |
|
67 |
"address": ("address", "The IP address"), |
|
68 |
"server": ("server_id", "The the server connected to"), |
|
69 |
"network": ("network_id", "The id of the network"), |
|
70 |
"allocated_at": ("allocated_at", "Datetime IP allocated to server"), |
|
71 |
"released_at": ("released_at", "Datetime IP released from server"), |
|
72 |
"active": ("active", "Whether IP still allocated to server"), |
|
73 |
} |
|
74 |
|
|
75 |
fields = ["address", "server", "network", "allocated_at", "released_at"] |
|
76 |
|
|
77 |
def handle_args(self, *args, **options): |
|
78 |
if options["address"]: |
|
79 |
self.filters["address"] = options["address"] |
|
80 |
if options["server"]: |
|
81 |
self.filters["server_id"] = options["server"] |
|
82 |
if options["active"]: |
|
83 |
self.filters["active"] = True |
/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 |
|
|
36 |
from django.core.management.base import BaseCommand, CommandError |
|
37 |
from synnefo.management.common import convert_api_faults |
|
38 |
from snf_django.management.utils import parse_bool |
|
39 |
|
|
40 |
from synnefo.db.models import Network |
|
41 |
from synnefo.logic import networks, subnets |
|
42 |
from synnefo.management import pprint |
|
43 |
|
|
44 |
import ipaddr |
|
45 |
|
|
46 |
NETWORK_FLAVORS = Network.FLAVORS.keys() |
|
47 |
|
|
48 |
|
|
49 |
class Command(BaseCommand): |
|
50 |
can_import_settings = True |
|
51 |
output_transaction = True |
|
52 |
|
|
53 |
help = "Create a new network" |
|
54 |
|
|
55 |
option_list = BaseCommand.option_list + ( |
|
56 |
make_option( |
|
57 |
'--name', |
|
58 |
dest='name', |
|
59 |
help="Name of the network"), |
|
60 |
make_option( |
|
61 |
'--owner', |
|
62 |
dest='owner', |
|
63 |
help="The owner of the network"), |
|
64 |
make_option( |
|
65 |
'--subnet', |
|
66 |
dest='subnet', |
|
67 |
default=None, |
|
68 |
# required=True, |
|
69 |
help='IPv4 subnet of the network'), |
|
70 |
make_option( |
|
71 |
'--gateway', |
|
72 |
dest='gateway', |
|
73 |
default=None, |
|
74 |
help='IPv4 gateway of the network'), |
|
75 |
make_option( |
|
76 |
'--subnet6', |
|
77 |
dest='subnet6', |
|
78 |
default=None, |
|
79 |
help='IPv6 subnet of the network'), |
|
80 |
make_option( |
|
81 |
'--gateway6', |
|
82 |
dest='gateway6', |
|
83 |
default=None, |
|
84 |
help='IPv6 gateway of the network'), |
|
85 |
make_option( |
|
86 |
'--dhcp', |
|
87 |
dest='dhcp', |
|
88 |
default="False", |
|
89 |
choices=["True", "False"], |
|
90 |
metavar="True|False", |
|
91 |
help='Automatically assign IPs'), |
|
92 |
make_option( |
|
93 |
'--public', |
|
94 |
dest='public', |
|
95 |
action='store_true', |
|
96 |
default=False, |
|
97 |
help='Network is public'), |
|
98 |
make_option( |
|
99 |
'--flavor', |
|
100 |
dest='flavor', |
|
101 |
default=None, |
|
102 |
choices=NETWORK_FLAVORS, |
|
103 |
help='Network flavor. Choices: ' + ', '.join(NETWORK_FLAVORS)), |
|
104 |
make_option( |
|
105 |
'--mode', |
|
106 |
dest='mode', |
|
107 |
default=None, |
|
108 |
help="Overwrite flavor connectivity mode."), |
|
109 |
make_option( |
|
110 |
'--link', |
|
111 |
dest='link', |
|
112 |
default=None, |
|
113 |
help="Overwrite flavor connectivity link."), |
|
114 |
make_option( |
|
115 |
'--mac-prefix', |
|
116 |
dest='mac_prefix', |
|
117 |
default=None, |
|
118 |
help="Overwrite flavor connectivity MAC prefix"), |
|
119 |
make_option( |
|
120 |
'--tags', |
|
121 |
dest='tags', |
|
122 |
default=None, |
|
123 |
help='The tags of the Network (comma separated strings)'), |
|
124 |
make_option( |
|
125 |
'--floating-ip-pool', |
|
126 |
dest='floating_ip_pool', |
|
127 |
default="False", |
|
128 |
choices=["True", "False"], |
|
129 |
metavar="True|False", |
|
130 |
help="Use the network as a Floating IP pool."), |
|
131 |
make_option( |
|
132 |
'--allocation-pool', |
|
133 |
dest='allocation_pools', |
|
134 |
action='append', |
|
135 |
help="IP allocation pools to be used for assigning IPs to" |
|
136 |
" VMs. Can be used multiple times. Syntax: \n" |
|
137 |
"192.168.42.220,192.168.42.240. Starting IP must proceed " |
|
138 |
"ending IP. If no allocation pools are given, the whole " |
|
139 |
"subnet range is used, excluding the gateway IP, the " |
|
140 |
"broadcast address and the network address"), |
|
141 |
) |
|
142 |
|
|
143 |
@convert_api_faults |
|
144 |
def handle(self, *args, **options): |
|
145 |
if args: |
|
146 |
raise CommandError("Command doesn't accept any arguments") |
|
147 |
|
|
148 |
name = options['name'] |
|
149 |
subnet = options['subnet'] |
|
150 |
gateway = options['gateway'] |
|
151 |
subnet6 = options['subnet6'] |
|
152 |
gateway6 = options['gateway6'] |
|
153 |
public = options['public'] |
|
154 |
flavor = options['flavor'] |
|
155 |
mode = options['mode'] |
|
156 |
link = options['link'] |
|
157 |
mac_prefix = options['mac_prefix'] |
|
158 |
tags = options['tags'] |
|
159 |
userid = options["owner"] |
|
160 |
allocation_pools = options["allocation_pools"] |
|
161 |
floating_ip_pool = parse_bool(options["floating_ip_pool"]) |
|
162 |
dhcp = parse_bool(options["dhcp"]) |
|
163 |
|
|
164 |
if name is None: |
|
165 |
name = "" |
|
166 |
if flavor is None: |
|
167 |
raise CommandError("flavor is required") |
|
168 |
|
|
169 |
if ((subnet is None) and (subnet6 is None)) and dhcp is not False: |
|
170 |
raise CommandError("Cannot set DHCP without subnet or subnet6") |
|
171 |
|
|
172 |
if subnet is None and gateway is not None: |
|
173 |
raise CommandError("Cannot use gateway without subnet") |
|
174 |
if subnet is None and allocation_pools is not None: |
|
175 |
raise CommandError("Cannot use allocation-pools without subnet") |
|
176 |
if subnet6 is None and gateway6 is not None: |
|
177 |
raise CommandError("Cannot use gateway6 without subnet6") |
|
178 |
|
|
179 |
if not (userid or public): |
|
180 |
raise CommandError("'owner' is required for private networks") |
|
181 |
|
|
182 |
network = networks.create(userid=userid, name=name, flavor=flavor, |
|
183 |
public=public, mode=mode, |
|
184 |
link=link, mac_prefix=mac_prefix, tags=tags, |
|
185 |
floating_ip_pool=floating_ip_pool) |
|
186 |
|
|
187 |
if subnet is not None: |
|
188 |
alloc = None |
|
189 |
if allocation_pools is not None: |
|
190 |
alloc = subnets.parse_allocation_pools(allocation_pools) |
|
191 |
alloc.sort() |
|
192 |
name = "IPv4 Subnet of Network %s" % network.id |
|
193 |
subnets.create_subnet(network.id, cidr=subnet, name=name, |
|
194 |
ipversion=4, gateway=gateway, dhcp=dhcp, |
|
195 |
user_id=userid, |
|
196 |
allocation_pools=alloc) |
|
197 |
|
|
198 |
if subnet6 is not None: |
|
199 |
name = "IPv6 Subnet of Network %s" % network.id |
|
200 |
subnets.create_subnet(network.id, cidr=subnet6, name=name, |
|
201 |
ipversion=6, gateway=gateway6, |
|
202 |
dhcp=dhcp, user_id=userid) |
|
203 |
|
|
204 |
self.stdout.write("Created network '%s' in DB:\n" % network) |
|
205 |
pprint.pprint_network(network, stdout=self.stdout) |
|
206 |
pprint.pprint_network_subnets(network, stdout=self.stdout) |
|
207 |
|
|
208 |
networks.create_network_in_backends(network) |
|
209 |
# TODO: Add --wait option to track job progress and report successful |
|
210 |
# creation in each backend. |
|
211 |
self.stdout.write("\nSuccessfully issued job to create network in" |
|
212 |
" backends\n") |
/dev/null | ||
---|---|---|
1 |
# Copyright 2012-2013 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 |
|
|
36 |
from snf_django.management.commands import ListCommand |
|
37 |
from synnefo.db.models import Network |
|
38 |
from synnefo.settings import (CYCLADES_SERVICE_TOKEN as ASTAKOS_TOKEN, |
|
39 |
ASTAKOS_AUTH_URL) |
|
40 |
|
|
41 |
from logging import getLogger |
|
42 |
log = getLogger(__name__) |
|
43 |
|
|
44 |
|
|
45 |
class Command(ListCommand): |
|
46 |
help = "List networks" |
|
47 |
|
|
48 |
option_list = ListCommand.option_list + ( |
|
49 |
make_option( |
|
50 |
'--public', |
|
51 |
action='store_true', |
|
52 |
dest='public', |
|
53 |
default=False, |
|
54 |
help="List only public networks"), |
|
55 |
make_option( |
|
56 |
'--ipv6', |
|
57 |
action='store_true', |
|
58 |
dest='ipv6', |
|
59 |
default=False, |
|
60 |
help="Include IPv6 information"), |
|
61 |
) |
|
62 |
|
|
63 |
object_class = Network |
|
64 |
select_related = [] |
|
65 |
prefetch_related = ["subnets"] |
|
66 |
deleted_field = "deleted" |
|
67 |
user_uuid_field = "userid" |
|
68 |
astakos_auth_url = ASTAKOS_AUTH_URL |
|
69 |
astakos_token = ASTAKOS_TOKEN |
|
70 |
|
|
71 |
def get_machines(network): |
|
72 |
return network.machines.filter(deleted=False).count() |
|
73 |
|
|
74 |
def get_backends(network): |
|
75 |
return network.backend_networks.values_list("backend_id", flat=True) |
|
76 |
|
|
77 |
def get_subnet_ipv4(network): |
|
78 |
return _get_subnet_field(network, "cidr", 4) |
|
79 |
|
|
80 |
def get_subnet_ipv6(network): |
|
81 |
return _get_subnet_field(network, "cidr", 6) |
|
82 |
|
|
83 |
def get_gateway_ipv4(network): |
|
84 |
return _get_subnet_field(network, "gateway", 4) |
|
85 |
|
|
86 |
def get_gateway_ipv6(network): |
|
87 |
return _get_subnet_field(network, "gateway", 6) |
|
88 |
|
|
89 |
def get_subnets(network): |
|
90 |
return network.subnets.values_list('id', flat=True) |
|
91 |
|
|
92 |
FIELDS = { |
|
93 |
"id": ("id", "The ID of the network"), |
|
94 |
"name": ("name", "The name of the network"), |
|
95 |
"user.uuid": ("userid", "The UUID of the network's owner"), |
|
96 |
"public": ("public", "Whether network is public or private"), |
|
97 |
"flavor": ("flavor", "The network's flavor"), |
|
98 |
"state": ("state", "The network's state"), |
|
99 |
"subnets": (get_subnets, "The IDs of the associated subnets"), |
|
100 |
"subnet.ipv4": (get_subnet_ipv4, "The IPv4 subnet of the network"), |
|
101 |
"gateway.ipv4": (get_gateway_ipv4, "The IPv4 gateway of the network"), |
|
102 |
"subnet.ipv6": (get_subnet_ipv6, "The IPv6 subnet of the network"), |
|
103 |
"gateway.ipv6": (get_gateway_ipv6, "The IPv6 gateway of the network"), |
|
104 |
"created": ("created", "The date the network was created"), |
|
105 |
"updated": ("updated", "The date the network was updated"), |
|
106 |
"deleted": ("deleted", "Whether the network is deleted or not"), |
|
107 |
"mode": ("mode", "The mode of the network"), |
|
108 |
"link": ("link", "The link of the network"), |
|
109 |
"mac_prefix": ("mac_prefix", "The network's MAC prefix"), |
|
110 |
"drained": ("drained", "Whether network is drained or not"), |
|
111 |
"vms": (get_machines, "Number of connected servers"), |
|
112 |
"backends": (get_backends, "IDs of Ganeti backends that the network is" |
|
113 |
" connected to"), |
|
114 |
"floating_ip_pool": ("floating_ip_pool", |
|
115 |
"Whether the network is a floating IP pool"), |
|
116 |
} |
|
117 |
|
|
118 |
fields = ["id", "name", "user.uuid", "state", "public", "subnet.ipv4", |
|
119 |
"gateway.ipv4", "link", "mac_prefix", "drained", |
|
120 |
"floating_ip_pool"] |
|
121 |
|
|
122 |
def handle_args(self, *args, **options): |
|
123 |
if options["public"]: |
|
124 |
self.filters["public"] = True |
|
125 |
if options["ipv6"]: |
|
126 |
self.fields.extend(["subnet.ipv6", "gateway.ipv6"]) |
|
127 |
|
|
128 |
|
|
129 |
def _get_subnet_field(network, field, version=4): |
|
130 |
for subnet in network.subnets.all(): |
|
131 |
if subnet.ipversion == version: |
|
132 |
return getattr(subnet, field) |
|
133 |
return None |
/dev/null | ||
---|---|---|
1 |
# Copyright 2012-2013 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 |
|
|
36 |
from django.core.management.base import BaseCommand, CommandError |
|
37 |
|
|
38 |
from synnefo.db.models import Backend |
|
39 |
from synnefo.management.common import (get_network, get_backend) |
|
40 |
from snf_django.management.utils import parse_bool |
|
41 |
from synnefo.logic import networks, backend as backend_mod |
|
42 |
from django.db import transaction |
|
43 |
|
|
44 |
|
|
45 |
class Command(BaseCommand): |
|
46 |
args = "<network id>" |
|
47 |
help = "Modify a network." |
|
48 |
|
|
49 |
option_list = BaseCommand.option_list + ( |
|
50 |
make_option( |
|
51 |
'--name', |
|
52 |
dest='name', |
|
53 |
metavar='NAME', |
|
54 |
help="Rename a network"), |
|
55 |
make_option( |
|
56 |
'--userid', |
|
57 |
dest='userid', |
|
58 |
help="Change the owner of the network."), |
|
59 |
make_option( |
|
60 |
"--drained", |
|
61 |
dest="drained", |
|
62 |
metavar="True|False", |
|
63 |
choices=["True", "False"], |
|
64 |
help="Set as drained to exclude for IP allocation." |
|
65 |
" Only used for public networks."), |
|
66 |
make_option( |
|
67 |
"--floating-ip-pool", |
|
68 |
dest="floating_ip_pool", |
|
69 |
metavar="True|False", |
|
70 |
choices=["True", "False"], |
|
71 |
help="Convert network to a floating IP pool. During this" |
|
72 |
" conversation the network will be created to all" |
|
73 |
" available Ganeti backends."), |
|
74 |
make_option( |
|
75 |
'--add-reserved-ips', |
|
76 |
dest="add_reserved_ips", |
|
77 |
help="Comma seperated list of IPs to externally reserve."), |
|
78 |
make_option( |
|
79 |
'--remove-reserved-ips', |
|
80 |
dest="remove_reserved_ips", |
|
81 |
help="Comma seperated list of IPs to externally release."), |
|
82 |
make_option( |
|
83 |
"--add-to-backend", |
|
84 |
dest="add_to_backend", |
|
85 |
metavar="BACKEND_ID", |
|
86 |
help="Create a network to a Ganeti backend."), |
|
87 |
make_option( |
|
88 |
"--remove-from-backend", |
|
89 |
dest="remove_from_backend", |
|
90 |
metavar="BACKEND_ID", |
|
91 |
help="Remove a network from a Ganeti backend."), |
|
92 |
) |
|
93 |
|
|
94 |
@transaction.commit_on_success |
|
95 |
def handle(self, *args, **options): |
|
96 |
if len(args) != 1: |
|
97 |
raise CommandError("Please provide a network ID") |
|
98 |
|
|
99 |
network = get_network(args[0]) |
|
100 |
|
|
101 |
new_name = options.get("name") |
|
102 |
if new_name is not None: |
|
103 |
old_name = network.name |
|
104 |
network = networks.rename(network, new_name) |
|
105 |
self.stdout.write("Renamed network '%s' from '%s' to '%s'.\n" % |
|
106 |
(network, old_name, new_name)) |
|
107 |
|
|
108 |
drained = options.get("drained") |
|
109 |
if drained is not None: |
|
110 |
drained = parse_bool(drained) |
|
111 |
network.drained = drained |
|
112 |
network.save() |
|
113 |
self.stdout.write("Set network '%s' as drained=%s.\n" % |
|
114 |
(network, drained)) |
|
115 |
|
|
116 |
new_owner = options.get("userid") |
|
117 |
if new_owner is not None: |
|
118 |
if "@" in new_owner: |
|
119 |
raise CommandError("Invalid owner UUID.") |
|
120 |
old_owner = network.userid |
|
121 |
network.userid = new_owner |
|
122 |
network.save() |
|
123 |
msg = "Changed the owner of network '%s' from '%s' to '%s'.\n" |
|
124 |
self.stdout.write(msg % (network, old_owner, new_owner)) |
|
125 |
|
|
126 |
floating_ip_pool = options["floating_ip_pool"] |
|
127 |
if floating_ip_pool is not None: |
|
128 |
floating_ip_pool = parse_bool(floating_ip_pool) |
|
129 |
if floating_ip_pool is False and network.floating_ip_pool is True: |
|
130 |
if network.ips.filter(deleted=False, floating_ip=True)\ |
|
131 |
.exists(): |
|
132 |
msg = ("Cannot make network a non floating IP pool." |
|
133 |
" There are still reserved floating IPs.") |
|
134 |
raise CommandError(msg) |
|
135 |
network.floating_ip_pool = floating_ip_pool |
|
136 |
network.save() |
|
137 |
self.stdout.write("Set network '%s' as floating-ip-pool=%s.\n" % |
|
138 |
(network, floating_ip_pool)) |
|
139 |
if floating_ip_pool is True: |
|
140 |
for backend in Backend.objects.filter(offline=False): |
|
141 |
bnet, jobs =\ |
|
142 |
backend_mod.ensure_network_is_active(backend, |
|
143 |
network.id) |
|
144 |
if jobs: |
|
145 |
msg = ("Sent job to create network '%s' in backend" |
|
146 |
" '%s'\n" % (network, backend)) |
|
147 |
self.stdout.write(msg) |
|
148 |
|
|
149 |
add_reserved_ips = options.get('add_reserved_ips') |
|
150 |
remove_reserved_ips = options.get('remove_reserved_ips') |
|
151 |
if add_reserved_ips or remove_reserved_ips: |
|
152 |
if add_reserved_ips: |
|
153 |
add_reserved_ips = add_reserved_ips.split(",") |
|
154 |
for ip in add_reserved_ips: |
|
155 |
network.reserve_address(ip, external=True) |
|
156 |
if remove_reserved_ips: |
|
157 |
remove_reserved_ips = remove_reserved_ips.split(",") |
|
158 |
for ip in remove_reserved_ips: |
|
159 |
network.release_address(ip, external=True) |
|
160 |
|
|
161 |
add_to_backend = options["add_to_backend"] |
|
162 |
if add_to_backend is not None: |
|
163 |
backend = get_backend(add_to_backend) |
|
164 |
bnet, jobs = backend_mod.ensure_network_is_active(backend, |
|
165 |
network.id) |
|
166 |
if jobs: |
|
167 |
msg = "Sent job to create network '%s' in backend '%s'\n" |
|
168 |
self.stdout.write(msg % (network, backend)) |
|
169 |
|
|
170 |
remove_from_backend = options["remove_from_backend"] |
|
171 |
if remove_from_backend is not None: |
|
172 |
backend = get_backend(remove_from_backend) |
|
173 |
if network.nics.filter(machine__backend=backend, |
|
174 |
machine__deleted=False).exists(): |
|
175 |
msg = "Cannot remove. There are still connected VMs to this"\ |
|
176 |
" network" |
|
177 |
raise CommandError(msg) |
|
178 |
backend_mod.delete_network(network, backend, disconnect=True) |
|
179 |
msg = "Sent job to delete network '%s' from backend '%s'\n" |
|
180 |
self.stdout.write(msg % (network, backend)) |
/dev/null | ||
---|---|---|
1 |
# Copyright 2011-2013 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 django.core.management.base import CommandError |
|
32 |
from snf_django.management.commands import RemoveCommand |
|
33 |
from snf_django.lib.api import faults |
|
34 |
from synnefo.logic import networks |
|
35 |
from synnefo.management.common import get_network, convert_api_faults |
|
36 |
|
|
37 |
|
|
38 |
class Command(RemoveCommand): |
|
39 |
can_import_settings = True |
|
40 |
args = "<Network ID> [<Network ID> ...]" |
|
41 |
help = "Remove a network from the Database, and Ganeti" |
|
42 |
|
|
43 |
@convert_api_faults |
|
44 |
def handle(self, *args, **options): |
|
45 |
if not args: |
|
46 |
raise CommandError("Please provide a network ID") |
|
47 |
|
|
48 |
force = options['force'] |
Also available in: Unified diff