65
def host_dict(host, compute_service, instances, volume_service, volumes, now):
66
54
"""Convert a host model object to a result dict"""
67
rv = {'hostname': host, 'instance_count': len(instances),
68
'volume_count': len(volumes)}
70
latest = compute_service['updated_at'] or compute_service['created_at']
72
if delta.seconds <= FLAGS.service_down_time:
75
rv['compute'] = 'down'
77
latest = volume_service['updated_at'] or volume_service['created_at']
79
if delta.seconds <= FLAGS.service_down_time:
86
def instance_dict(inst):
87
return {'name': inst['name'],
88
'memory_mb': inst['memory_mb'],
89
'vcpus': inst['vcpus'],
90
'disk_gb': inst['local_gb'],
91
'flavor_id': inst['flavorid']}
94
def vpn_dict(project, vpn_instance):
95
rv = {'project_id': project.id,
96
'public_ip': project.vpn_ip,
97
'public_port': project.vpn_port}
99
rv['instance_id'] = ec2utils.id_to_ec2_id(vpn_instance['id'])
100
rv['created_at'] = utils.isotime(vpn_instance['created_at'])
101
address = vpn_instance.get('fixed_ip', None)
103
rv['internal_ip'] = address['address']
104
if project.vpn_ip and project.vpn_port:
105
if utils.vpn_ping(project.vpn_ip, project.vpn_port):
106
rv['state'] = 'running'
110
rv['state'] = 'down - invalid project vpn config'
112
rv['state'] = 'pending'
116
61
class AdminController(object):
138
75
return {'userSet':
139
76
[user_dict(u) for u in manager.AuthManager().get_users()]}
141
def register_user(self, context, name, **_kwargs):
78
def register_user(self, _context, name, **_kwargs):
142
79
"""Creates a new user, and returns generated credentials."""
143
LOG.audit(_("Creating new user: %s"), name, context=context)
144
80
return user_dict(manager.AuthManager().create_user(name))
146
def deregister_user(self, context, name, **_kwargs):
82
def deregister_user(self, _context, name, **_kwargs):
147
83
"""Deletes a single user (NOT undoable.)
148
84
Should throw an exception if the user has instances,
149
85
volumes, or buckets remaining.
151
LOG.audit(_("Deleting user: %s"), name, context=context)
152
87
manager.AuthManager().delete_user(name)
155
91
def describe_roles(self, context, project_roles=True, **kwargs):
169
105
operation='add', **kwargs):
170
106
"""Add or remove a role for a user and project."""
171
107
if operation == 'add':
173
msg = _("Adding role %(role)s to user %(user)s"
174
" for project %(project)s") % locals()
175
LOG.audit(msg, context=context)
177
msg = _("Adding sitewide role %(role)s to"
178
" user %(user)s") % locals()
179
LOG.audit(msg, context=context)
180
108
manager.AuthManager().add_role(user, role, project)
181
109
elif operation == 'remove':
183
msg = _("Removing role %(role)s from user %(user)s"
184
" for project %(project)s") % locals()
185
LOG.audit(msg, context=context)
187
msg = _("Removing sitewide role %(role)s"
188
" from user %(user)s") % locals()
189
LOG.audit(msg, context=context)
190
110
manager.AuthManager().remove_role(user, role, project)
192
raise exception.ApiError(_('operation must be add or remove'))
112
raise exception.ApiError('operation must be add or remove')
196
def generate_x509_for_user(self, context, name, project=None, **kwargs):
116
def generate_x509_for_user(self, _context, name, project=None, **kwargs):
197
117
"""Generates and returns an x509 certificate for a single user.
198
118
Is usually called from a client that will wrap this with
199
119
access and secret key info, and return a zip file.
258
160
"""Add or remove a user from a project."""
259
161
if operation == 'add':
260
msg = _("Adding user %(user)s to project %(project)s") % locals()
261
LOG.audit(msg, context=context)
262
162
manager.AuthManager().add_to_project(user, project)
263
163
elif operation == 'remove':
264
msg = _("Removing user %(user)s from"
265
" project %(project)s") % locals()
266
LOG.audit(msg, context=context)
267
164
manager.AuthManager().remove_from_project(user, project)
269
raise exception.ApiError(_('operation must be add or remove'))
166
raise exception.ApiError('operation must be add or remove')
272
def _vpn_for(self, context, project_id):
273
"""Get the VPN instance for a project ID."""
274
for instance in db.instance_get_all_by_project(context, project_id):
275
if (instance['image_id'] == str(FLAGS.vpn_image_id)
276
and not instance['vm_state'] in [vm_states.DELETED]):
279
def start_vpn(self, context, project):
280
instance = self._vpn_for(context, project)
282
# NOTE(vish) import delayed because of __init__.py
283
from nova.cloudpipe import pipelib
284
pipe = pipelib.CloudPipe()
285
proj = manager.AuthManager().get_project(project)
286
user_id = proj.project_manager_id
288
pipe.launch_vpn_instance(project, user_id)
289
except db.NoMoreNetworks:
290
raise exception.ApiError("Unable to claim IP for VPN instance"
291
", ensure it isn't running, and try "
292
"again in a few minutes")
293
instance = self._vpn_for(context, project)
294
return {'instance_id': ec2utils.id_to_ec2_id(instance['id'])}
296
def describe_vpns(self, context):
298
for project in manager.AuthManager().get_projects():
299
instance = self._vpn_for(context, project.id)
300
vpns.append(vpn_dict(project, instance))
301
return {'items': vpns}
303
169
# FIXME(vish): these host commands don't work yet, perhaps some of the
304
170
# required data can be retrieved from service objects?
306
def describe_hosts(self, context, **_kwargs):
171
def describe_hosts(self, _context, **_kwargs):
307
172
"""Returns status info for all nodes. Includes:
309
* Compute (up, down, None)
311
* Volume (up, down, None)
177
* DHCP servers running
314
services = db.service_get_all(context, False)
318
for host in [service['host'] for service in services]:
319
if not host in hosts:
322
compute = [s for s in services if s['host'] == host \
323
and s['binary'] == 'nova-compute']
326
instances = db.instance_get_all_by_host(context, host)
327
volume = [s for s in services if s['host'] == host \
328
and s['binary'] == 'nova-volume']
331
volumes = db.volume_get_all_by_host(context, host)
332
rv.append(host_dict(host, compute, instances, volume, volumes,
336
def _provider_fw_rule_exists(self, context, rule):
337
# TODO(todd): we call this repeatedly, can we filter by protocol?
338
for old_rule in db.provider_fw_rule_get_all(context):
339
if all([rule[k] == old_rule[k] for k in ('cidr', 'from_port',
340
'to_port', 'protocol')]):
344
def block_external_addresses(self, context, cidr):
345
"""Add provider-level firewall rules to block incoming traffic."""
346
LOG.audit(_('Blocking traffic to all projects incoming from %s'),
347
cidr, context=context)
348
cidr = urllib.unquote(cidr).decode()
350
netaddr.IPNetwork(cidr)
351
rule = {'cidr': cidr}
352
tcp_rule = rule.copy()
353
tcp_rule.update({'protocol': 'tcp', 'from_port': 1, 'to_port': 65535})
354
udp_rule = rule.copy()
355
udp_rule.update({'protocol': 'udp', 'from_port': 1, 'to_port': 65535})
356
icmp_rule = rule.copy()
357
icmp_rule.update({'protocol': 'icmp', 'from_port': -1,
360
if not self._provider_fw_rule_exists(context, tcp_rule):
361
db.provider_fw_rule_create(context, tcp_rule)
363
if not self._provider_fw_rule_exists(context, udp_rule):
364
db.provider_fw_rule_create(context, udp_rule)
366
if not self._provider_fw_rule_exists(context, icmp_rule):
367
db.provider_fw_rule_create(context, icmp_rule)
370
raise exception.ApiError(_('Duplicate rule'))
371
self.compute_api.trigger_provider_fw_rules_refresh(context)
372
return {'status': 'OK', 'message': 'Added %s rules' % rules_added}
374
def describe_external_address_blocks(self, context):
375
blocks = db.provider_fw_rule_get_all(context)
376
# NOTE(todd): use a set since we have icmp/udp/tcp rules with same cidr
377
blocks = set([b.cidr for b in blocks])
378
blocks = [{'cidr': b} for b in blocks]
379
return {'externalIpBlockInfo':
380
list(sorted(blocks, key=lambda k: k['cidr']))}
382
def remove_external_address_block(self, context, cidr):
383
LOG.audit(_('Removing ip block from %s'), cidr, context=context)
384
cidr = urllib.unquote(cidr).decode()
386
netaddr.IPNetwork(cidr)
387
rules = db.provider_fw_rule_get_all_by_cidr(context, cidr)
389
db.provider_fw_rule_destroy(context, rule['id'])
391
self.compute_api.trigger_provider_fw_rules_refresh(context)
392
return {'status': 'OK', 'message': 'Deleted %s rules' % len(rules)}
180
return {'hostSet': [host_dict(h) for h in db.host_get_all()]}
182
def describe_host(self, _context, name, **_kwargs):
183
"""Returns status info for single node."""
184
return host_dict(db.host_get(name))