def action_purge(): active = ksclient.get_users(domain=options.domain, enabled=True) users = ksclient.get_users(domain=options.domain, enabled=False) count = 0 disabled = list() for user in users: if not hasattr(user, 'disabled'): himutils.sys_error( "user %s is disabled but missing disabled date" % user.name) continue # Allow 30 days gracetime before we delete disabled_date = himutils.get_date(user.disabled, None, '%Y-%m-%d') gracetime = timedelta(30) if date.today() - disabled_date < gracetime: continue if options.org != 'all': org = ksclient.get_user_org(user.name) if org and org != options.org: continue if options.limit and count >= int(options.limit): break count += 1 disabled.append(user) q = 'This will delete %s disabled users (total active users %s)' \ % (len(disabled), len(active)) if not himutils.confirm_action(q): return for user in disabled: ksclient.user_cleanup(email=user.name) print "%s deleted" % user.name
def action_rename(): if not ksclient.is_valid_user(email=options.old): himutils.sys_error('User %s not found as a valid user.' % options.old) personal = ksclient.get_project_name(options.new, prefix='PRIVATE') new_demo_project = ksclient.get_project_name(options.new) old_demo_project = ksclient.get_project_name(options.old) print "\nYou are about to rename user with email %s to %s" % (options.old, options.new) print "\nWhen a user changes affilation we need to change the following:" # new print " * Delete %s-group if it exists" % options.new print " * Delete %s api user if it exists" % options.new.lower() print " * Delete %s dataporten user if it exists" % options.new.lower() print " * Delete %s demo project and instances if exists" % new_demo_project print " * Delete %s personal project and instances if exist" % personal # old print " * Rename group from %s-group to %s-group" % (options.old, options.new) print " * Rename api user from %s to %s" % (options.old.lower(), options.new.lower()) print " * Rename demo project from %s to %s" % (old_demo_project, new_demo_project) print " * Delete old dataporten user %s" % (options.old) question = "\nAre you sure you will continue" if not himutils.confirm_action(question): return print 'Please wait...' ksclient.user_cleanup(email=options.new) ksclient.rename_user(new_email=options.new, old_email=options.old)
def action_delete(): status_id = options.status_id if not himutils.confirm_action( 'Are you sure you want to delete status message with id %s' % status_id): return status.delete(status_id)
def action_delete(): node_name = '%s-%s' % (region, options.node) if not options.assume_yes: if not himutils.confirm_action('Are you sure you want to delete %s?' % node_name): return client.delete_node(node_name) sensu.delete_client(node_name)
def action_rename(): if not ksclient.is_valid_user(email=options.old): himutils.sys_error('User %s not found as a valid user.' % options.old) personal = ksclient.get_project_name(options.new, prefix='PRIVATE') new_demo_project = ksclient.get_project_name(options.new) old_demo_project = ksclient.get_project_name(options.old) print "\nYou are about to rename user with email %s to %s" % (options.old, options.new) print "\nWhen a user changes affilation we need to change the following:" # new print " * Delete %s-group if it exists" % options.new print " * Delete %s api user if it exists" % options.new.lower() print " * Delete %s dataporten user if it exists" % options.new.lower() print " * Delete %s demo project and instances if exists" % new_demo_project print " * Delete %s personal project and instances if exist" % personal # old print " * Rename group from %s-group to %s-group" % (options.old, options.new) print " * Rename api user from %s to %s" % (options.old.lower(), options.new.lower()) print " * Rename demo project from %s to %s" % (old_demo_project, new_demo_project) print " * Delete old dataporten user %s" % (options.old) question = "\nAre you sure you will continue" if not himutils.confirm_action(question): return print 'Please wait...' ksclient.user_cleanup(email=options.new) ksclient.rename_user(new_email=options.new, old_email=options.old)
def action_migrate(): target = nc.get_fqdn(options.target) target_details = nc.get_host(target) if not target_details or target_details.status != 'enabled': himutils.sys_error('Could not find enabled target host %s' % options.target) q = 'Migrate all instances from %s to %s' % (source, target) if not himutils.confirm_action(q): return # Disable source host unless no-disable param is used if not options.dry_run and not options.no_disable: nc.disable_host(source) dry_run_txt = 'DRY_RUN: ' if options.dry_run else '' instances = nc.get_all_instances(search_opts=search_opts) count = 0 for i in instances: if options.large: if i.flavor['ram'] > options.large_ram: migrate_instance(i, target) else: kc.debug_log('drop migrate instance %s: ram %s < %s' % (i.name, i.flavor['ram'], options.large_ram)) else: migrate_instance(i, target) count += 1 if options.limit and count >= options.limit: kc.debug_log('number of instances reached limit %s' % options.limit) break
def action_retire(): image_templates = himutils.load_config('config/images/%s' % options.image_config) if not image_templates or 'images' not in image_templates or 'type' not in image_templates: sys.stderr.write("Invalid yaml file (config/images/%s): images hash not found\n" % options.image_config) sys.exit(1) image_type = image_templates['type'] image_msg = options.name if options.name else 'all' question = "Retire all active images matching '%s'" % image_msg if not himutils.confirm_action(question): return found = False for name, image_data in image_templates['images'].iteritems(): if options.name and name != options.name: logger.debug('=> dropped %s: image name spesified', name) continue tags = list() tags.append(image_type) tags.append(name) filters = {'tag': tags, 'status': 'active'} logger.debug('=> filter: %s' % filters) images = glclient.find_image(filters=filters, limit=1) if images and len(images) > 0: if not options.dry_run: timestamp = datetime.utcnow().replace(microsecond=0).isoformat() glclient.update_image(image_id=images[0]['id'], name=image_data['depricated'], depricated=timestamp) glclient.deactivate(image_id=images[0]['id']) found = True if not found: print 'No image found in %s' % options.image_config
def action_purge(): tags = get_tags(names=True) tag_str = 'all tags' if not tags else '[' + ', '.join(tags) + ']' if not options.force and not utils.confirm_action( 'Purge unused {} deactive images matching {}'.format( options.visibility, tag_str)): return images = get_image_usage() count = 0 printer.output_dict({'header': 'Images deleted'}) limit = int(options.limit) if options.limit else options.limit for image in images.itervalues(): if image['count'] > 0: kc.debug_log('no purge: image {} in use!'.format(image['name'])) continue gc.delete_image(image['id']) out_image = { '1': image.name, '2': image.created_at, '3': '[' + ', '.join(image.tags) + ']' } printer.output_dict(out_image, sort=True, one_line=True) count += 1 # break purging if limit reached if limit and count >= int(limit): kc.debug_log('limit of {} reached'.format(limit)) break printer.output_dict({'header': 'Image count', 'count': count})
def action_delete(): question = 'Delete project %s and all resources' % options.project if not options.force and not himutils.confirm_action(question): return # Delete the project ksclient.delete_project(options.project) printer.output_msg('DELETED project: {}'.format(options.project))
def action_delete(): if not ksclient.is_valid_user(email=options.user): himutils.sys_error('User %s not found as a valid user.' % options.user) if not himutils.confirm_action('Delete user and all instances for %s' % options.user): return print "We are now deleting user, group, project and instances for %s" % options.user print 'Please wait...' ksclient.user_cleanup(email=options.user) print 'Delete successful'
def action_disable(): projects = ksclient.get_projects(domain=options.domain) project_list = list() for project in projects: found = False if hasattr(project, 'notify') and project.notify == 'converted': logger.debug('=> keep personal project. %s converted', project.name) continue if not project.enabled: logger.debug('=> personal project %s already disabled', project.name) continue if (hasattr(project, 'type') and project.type == 'personal' and 'PRIVATE' not in project.name): print "%s (new old personal project)" % project.name found = True elif '@' in project.name and not hasattr(project, 'type'): print "%s (old old personal project)" % project.name found = True #else: # logger.debug('=> project %s not old personal', project.name) if found: project_list.append(project) if len(project_list) == 0: print 'No project to disable' return question = 'Disable all personal project in list above' if options.dry_run: question = 'DRY-RUN: %s' % question if not himutils.confirm_action(question): return for project in project_list: # stop instances for region in regions: novaclient = Nova(options.config, debug=options.debug, log=logger, region=region) instances = novaclient.get_project_instances(project.id) for instance in instances: if not options.dry_run: if instance.status == 'ACTIVE': instance.stop() logger.debug('=> stop instance %s' % instance.name) time.sleep(2) else: logger.debug('=> DRY-RUN: stop instance %s' % instance.name) # disable project if not options.dry_run: ksclient.update_project(project_id=project.id, enabled=False) print 'Disable project %s' % project.name else: print 'DRY-RUN: disable project %s' % project.name
def action_expired(): max_days = 90 projects = kc.get_projects(type='demo') subject = '[NREC] Your demo instance is due for deletion' logfile = 'logs/demo-logs/expired_instances/demo-notify-expired-instances-{}.log'.format( date.today().isoformat()) mail = utils.get_client(Mail, options, logger) fromaddr = mail.get_config('mail', 'from_addr') cc = '*****@*****.**' inputday = options.day question = 'Send mail to instances that have been running for {} days?'.format( inputday) if not options.force and not utils.confirm_action(question): return template = options.template if not utils.file_exists(template, logger): utils.sys_error('Could not find template file {}'.format(template)) if not options.template: utils.sys_error( 'Specify a template file. E.g. -t notify/demo-notify-expired-instances.txt' ) if not options.day: utils.sys_error( 'Specify the number of days for running demo instances. E.g. -d 30' ) for region in regions: nc = utils.get_client(Nova, options, logger, region) for project in projects: instances = nc.get_project_instances(project_id=project.id) for instance in instances: created = utils.get_date(instance.created, None, '%Y-%m-%dT%H:%M:%SZ') active_days = (date.today() - created).days kc.debug_log('{} running for {} days'.format( instance.id, active_days)) if (int(active_days) == int(inputday)): mapping = dict(project=project.name, enddate=int((max_days) - int(inputday)), activity=int(active_days), region=region.upper(), instance=instance.name) body_content = utils.load_template(inputfile=template, mapping=mapping, log=logger) msg = mail.get_mime_text(subject, body_content, fromaddr, cc) kc.debug_log( 'Sending mail to {} that has been active for {} days'. format(instance.id, active_days)) mail.send_mail(project.admin, msg, fromaddr) utils.append_to_logfile(logfile, date.today(), region, project.admin, instance.name, active_days) print('Mail sendt to {}'.format(project.admin))
def action_delete(): if not ksclient.is_valid_user(email=options.user): himutils.sys_error('User %s not found as a valid user.' % options.user) if not options.force: if not himutils.confirm_action( 'Delete user and all instances for %s' % options.user): return print "We are now deleting user, group, project and instances for %s" % options.user print 'Please wait...' ksclient.user_cleanup(email=options.user) print 'Delete successful'
def action_deactivate(): if options.org == 'all': active, deactive, unknown = get_valid_users() else: active, deactive, unknown = get_valid_users(options.org) q = 'This will deactivate %s users (total active users %s)' \ % (len(deactive), active['total']) if not himutils.confirm_action(q): return subject = '[UH-IaaS] Your account have been disabled' regions = ksclient.find_regions() count = 0 users_deactivated = list() for email in deactive: user = ksclient.get_user_by_email(email, 'api') # Disable user and notify user if user.enabled: # notify user mail_user(email, 'notify/notify_deactivate.txt', subject) # Disable api user date = datetime.today().strftime('%Y-%m-%d') ksclient.update_user(user_id=user.id, enabled=False, disabled=date) else: continue projects = ksclient.get_user_projects(email) # Shutoff instances in demo and personal project. for project in projects: if not hasattr(project, 'type'): continue if project.type == 'demo' or project.type == 'personal': for region in regions: nc = Nova(options.config, debug=options.debug, log=logger, region=region) nc.set_dry_run(options.dry_run) instances = nc.get_project_instances(project.id) for i in instances: if not options.dry_run: count += 1 if i.status == 'ACTIVE': i.stop() nc.debug_log('stop instance %s' % i.id) users_deactivated.append(email) output = dict() output['header'] = 'Deactivated users:' output['users'] = users_deactivated printer.output_dict(output) output = dict() output['header'] = 'Stopped instances:' output['servers'] = count printer.output_dict(output)
def action_delete(): if not himutils.confirm_action( 'Delete user and all instances for %s' % options.user): return print "We are now deleting user, group, project and instances for %s" % options.user print 'Please wait...' result = ksclient.remove_user(email=options.user, domain=domain, dry_run=options.dry_run) if not result: print 'Delete failed! Run with debug for more information' else: print 'Delete successfull'
def action_purge(): if not himutils.confirm_action('Purge unused images'): return images = image_usage() for image in images.itervalues(): if image['count'] > 0: logger.debug('=> no purge: image %s in use!' % image['name']) continue log_msg = "delete image %s" % image['name'] if not options.dry_run: glclient.delete_image(image['id']) else: log_msg = "DRY-RUN: %s" % log_msg logger.debug('=> %s', log_msg)
def action_purge(): if not himutils.confirm_action('Purge unused images'): return images = image_usage() for image in images.itervalues(): if image['count'] > 0: logger.debug('=> no purge: image %s in use!' % image['name']) continue log_msg = "delete image %s" % image['name'] if not options.dry_run: glclient.delete_image(image['id']) else: log_msg = "DRY-RUN: %s" % log_msg logger.debug('=> %s', log_msg)
def action_delete(): q = 'Delete flavor class {} in region(s) {}'.format( options.flavor, ','.join(regions)) if not himutils.confirm_action(q): return for region in regions: nc = himutils.get_client(Nova, options, logger, region) nc.debug_log('Start delete all {} from region {}'.format( options.flavor, region)) result = nc.delete_flavors(class_filter=options.flavor) if result: printer.output_msg('Deleted all {} from region {}'.format( options.flavor, region)) else: printer.output_msg( 'Nothing to delete from region {}'.format(region))
def action_file(): q = 'Send mail template {} to all emails in {}'.format( options.template, options.email_file) if not utils.confirm_action(q): return sent_mail_counter = 0 mail = Mail(options.config, debug=options.debug) mail.set_dry_run(options.dry_run) body_content = utils.load_template(inputfile=options.template, mapping={}, log=logger) emails = utils.load_file(inputfile=options.email_file, log=logger) for email in emails: mail.mail_user(body_content, options.subject, email) sent_mail_counter += 1 mail.close() printer.output_dict({'header': 'Mail counter', 'count': sent_mail_counter})
def action_deactivate(): active, deactive, unknown = get_valid_users() q = 'This will deactivate %s users (total active users %s)' \ % (len(deactive), active['total']) if not himutils.confirm_action(q): return subject = '[UH-IaaS] Your account have been disabled' regions = ksclient.find_regions() count = 0 users_deactivated = list() for email in deactive: user = ksclient.get_user_by_email(email, 'api') # Disable user and notify user if user.enabled: # notify user mail_user(email, 'notify/notify_deactivate.txt', subject) # Disable api user date = datetime.today().strftime('%Y-%m-%d') ksclient.update_user(user_id=user.id, enabled=False, disabled=date) else: continue projects = ksclient.get_user_projects(email) # Shutoff instances in demo and personal project. for project in projects: if not hasattr(project, 'type'): continue if project.type == 'demo' or project.type == 'personal': for region in regions: nc = Nova(options.config, debug=options.debug, log=logger, region=region) nc.set_dry_run(options.dry_run) instances = nc.get_project_instances(project.id) for i in instances: if not options.dry_run: count += 1 if i.status == 'ACTIVE': i.stop() nc.debug_log('stop instance %s' % i.id) users_deactivated.append(email) output = dict() output['header'] = 'Deactivated users:' output['users'] = users_deactivated printer.output_dict(output) output = dict() output['header'] = 'Stopped instances:' output['servers'] = count printer.output_dict(output)
def action_update(): question = ( "This will delete the flavor and recreate it for all other " "changes than properties. Check project access after. Continue?") if not himutils.confirm_action(question): return for region in regions: flavors = get_flavor_config(region) public = flavors['public'] if 'public' in flavors else False properties = flavors[ 'properties'] if 'properties' in flavors else dict() if not properties or not properties.get( 'aggregate_instance_extra_specs:type', None): properties['aggregate_instance_extra_specs:type'] = 's== standard' if (options.flavor not in flavors or not isinstance(flavors[options.flavor], dict)): himutils.sys_error('%s hash not found in config' % options.flavor) nc = Nova(options.config, debug=options.debug, log=logger, region=region) nc.set_dry_run(options.dry_run) for name, spec in sorted(flavors[options.flavor].iteritems()): # Hack to override properties per flavor flavor_properties = properties.copy() if 'properties' in spec: for p_name, prop in spec['properties'].iteritems(): flavor_properties[p_name] = prop del spec['properties'] nc.update_flavor(name=name, spec=spec, properties=flavor_properties, public=public) # Update access access = nc.get_flavor_access(filters=options.flavor) all_projects = set() for name, projects in access.iteritems(): for project_id in projects: all_projects.add(project_id.tenant_id) for project in all_projects: nc.update_flavor_access(class_filter=options.flavor, project_id=project, action='grant')
def action_reinstall(): node_name = '%s-%s' % (region, options.node) if options.node in nodes: if not options.assume_yes: if not himutils.confirm_action('Are you sure you want to reinstall %s?' % node_name): return client.delete_node(node_name) if options.sensu_expire: sensu.silence_host(node_name, options.sensu_expire) else: sensu.delete_client(node_name) client.create_node(name=node_name, node_data=nodes[options.node], region=region) else: sys.stderr.write("Node %s not found in config/nodes/%s.yaml\n" % (options.node, region)) sys.exit(1)
def action_purge(): q = 'Purge flavors from class {} in region(s) {}'.format( options.flavor, ','.join(regions)) if not himutils.confirm_action(q): return for region in regions: flavors = get_flavor_config(region) nc = himutils.get_client(Nova, options, logger, region) nc.debug_log('Start purge of flavor class {} from region {}'.format( options.flavor, region)) result = nc.purge_flavors(class_filter=options.flavor, flavors=flavors) if result: printer.output_msg( 'Purged flavors of class {} from region {}'.format( options.flavor, region)) else: printer.output_msg( 'Nothing to purge from region {}'.format(region))
def action_retire(): tags = get_tags(names=True) # Load config file config_filename = 'config/images/{}'.format(options.image_config) if not utils.file_exists(config_filename, logger): utils.sys_error( 'Could not find config file {}'.format(config_filename)) image_config = utils.load_config('config/images/{}'.format( options.image_config)) # make sure we have image type set if not 'type' in image_config: utils.sys_error( 'Type missing in retire file {}'.format(config_filename)) tags.append(image_config['type']) tag_str = 'all tags' if not tags else '[' + ', '.join(tags) + ']' if 'images' not in image_config or 'type' not in image_config: utils.sys_error( 'Images hash not found in config file {}'.format(config_filename)) if options.name not in image_config['images']: utils.sys_error( 'Unable to retire {}. Missing from config file {}'.format( options.name, options.image_config)) # Point of no return if not options.force and not utils.confirm_action( 'Retire active images matching {}'.format(tag_str)): return # Find image(s) filters = {'status': 'active', 'tag': tags} kc.debug_log('filter: {}'.format(filters)) images = gc.get_images(filters=filters, limit=1) for image in images: new_name = image_config['images'][options.name]['depricated'] timestamp = datetime.utcnow().replace(microsecond=0).isoformat() gc.update_image(image_id=image['id'], name=new_name, depricated=timestamp) gc.deactivate(image_id=image['id']) printer.output_msg('Retire image {}'.format(image['name']))
def action_cleanup(): projects = ksclient.get_projects(domain=options.domain) project_list = list() for project in projects: # Only list disabled projects if project.enabled: continue if hasattr(project, 'notify'): print "%s (notified=%s)" % (project.name, project.notify) else: print "%s (disabled project)" % project.name project_list.append(project) if len(project_list) == 0: print 'No project to cleanup' return question = 'Cleanup all personal project in list above' if options.dry_run: question = 'DRY-RUN: %s' % question if not himutils.confirm_action(question): return count = 0 for project in project_list: # stop instances for region in regions: novaclient = Nova(options.config, debug=options.debug, log=logger, region=region) instances = novaclient.get_project_instances(project.id) for instance in instances: if instance.status == 'SHUTOFF': count += 1 if not options.dry_run: logger.debug('=> delete instance %s (%s)' % (instance.name, instance.id)) instance.delete() time.sleep(5) else: himutils.sys_error( 'instance %s not deleted! (%s)' % (instance.name, instance.id), 0) ksclient.delete_project(project_name=project.name, domain=options.domain) print "Deleted %s instances from %s projects" % (count, len(project_list))
def action_orphan(): question = "This will also purge all orphan volumes. Are you sure?" if options.purge and not utils.confirm_action(question): return cc = utils.get_client(Cinder, options, logger, region) volumes = cc.get_volumes(detailed=True) printer.output_dict({'header': 'Volumes (id, name, type)'}) count = {'count': 0, 'size': 0} for volume in volumes: project = kc.get_by_id('project', getattr(volume, 'os-vol-tenant-attr:tenant_id')) if project: # not orphan volume continue count = print_and_count(volume, count) if options.purge: cc.delete_volume(volume.id, True) printer.output_dict({ 'header': 'Count', 'volumes': count['count'], 'size': count['size']})
def action_evacuate(): source_host = nc.get_host(source) if source_host.state != 'down': himutils.sys_error( 'Evacuate failed. Source host need to be down! Use migrate') # Check that there are other valid hosts in the same aggregate hosts = nc.get_aggregate_hosts(options.aggregate) found_enabled = list() for host in hosts: if host.hypervisor_hostname == source: continue if host.status == 'enabled' and host.state == 'up': found_enabled.append(host.hypervisor_hostname) if not found_enabled: himutils.sys_error('Evacuate failed. No valid host in aggregate %s' % options.aggregate) logger.debug('=> valid host found %s', ", ".join(found_enabled)) # Interactive question q = 'Evacuate all instances from %s to other hosts' % source if not himutils.confirm_action(q): return instances = nc.get_all_instances(search_opts=search_opts) dry_run_txt = 'DRY_RUN: ' if options.dry_run else '' count = 0 for i in instances: state = getattr(i, 'OS-EXT-STS:vm_state') logger.debug('=> %sevacuate %s', dry_run_txt, i.name) if state == 'active' and not options.dry_run: i.evacuate() time.sleep(options.sleep) elif state == 'stopped' and not options.dry_run: i.evacuate() time.sleep(options.sleep) elif not options.dry_run: logger.debug('=> dropping evacuate of %s unknown state %s', i.name, state) count += 1 if options.limit and count > options.limit: logger.debug('=> number of instances reached limit %s', options.limit) break
def action_migrate(): # Find enabled aggregate aggregates = novaclient.get_aggregates() active_aggregate = 'unknown' for aggregate in aggregates: if aggregate not in legacy_aggregate: continue info = novaclient.get_aggregate(aggregate) if 'enabled' in info.metadata: active_aggregate = aggregate break if active_aggregate == 'unknown': himutils.sys_error('Could not find enabled aggregate to migrate to. Make sure to activate aggregate first!') q = 'Migrate all instances from %s to %s' % (options.aggregate, active_aggregate) if not himutils.confirm_action(q): return instances = novaclient.get_instances(options.aggregate, host) count = 0 target_host = next(iter(novaclient.get_aggregate_hosts(active_aggregate) or []), None) if not target_host: himutils.sys_error('Could not find valid host in aggregate %s' % active_aggregate) for instance in instances: count += 1 if options.dry_run: logger.debug('=> DRY-RUN: migrate instance %s' % unicode(instance.name)) else: logger.debug('=> migrate instance %s' % unicode(instance.name)) try: instance.migrate(host=target_host.hypervisor_hostname) time.sleep(2) if count%options.limit == 0 and (options.hard_limit and count < options.limit): logger.debug('=> sleep for %s seconds', options.sleep) time.sleep(options.sleep) except novaexc.BadRequest as e: sys.stderr.write("%s\n" % e) sys.stderr.write("Error found. Cancel migration!\n") break if options.hard_limit and count >= options.limit: logger.debug('=> use of hard limit and exit after %s instances', options.limit) break
def action_migrate(): # Find enabled aggregate aggregates = novaclient.get_aggregates() active_aggregate = 'unknown' for aggregate in aggregates: if aggregate not in legacy_aggregate: continue info = novaclient.get_aggregate(aggregate) if 'enabled' in info.metadata: active_aggregate = aggregate break if active_aggregate == 'unknown': himutils.sys_error('Could not find enabled aggregate to migrate to. Make sure to activate aggregate first!') q = 'Migrate all instances from %s to %s' % (options.aggregate, active_aggregate) if not himutils.confirm_action(q): return instances = novaclient.get_instances(options.aggregate, host) count = 0 target_host = next(iter(novaclient.get_aggregate_hosts(active_aggregate) or []), None) if not target_host: himutils.sys_error('Could not find valid host in aggregate %s' % active_aggregate) for instance in instances: count += 1 if options.dry_run: logger.debug('=> DRY-RUN: migrate instance %s' % unicode(instance.name)) else: logger.debug('=> migrate instance %s' % unicode(instance.name)) try: instance.migrate(host=target_host.hypervisor_hostname) time.sleep(2) if count%options.limit == 0 and (options.hard_limit and count < options.limit): logger.debug('=> sleep for %s seconds', options.sleep) time.sleep(options.sleep) except novaexc.BadRequest as e: sys.stderr.write("%s\n" % e) sys.stderr.write("Error found. Cancel migration!\n") break if options.hard_limit and count >= options.limit: logger.debug('=> use of hard limit and exit after %s instances', options.limit) break
def action_migrate(): target = nc.get_fqdn(options.target) if not nc.get_host(target): himutils.sys_error('Could not find target host %s' % target) q = 'Migrate all instances from %s to %s' % (source, target) if not himutils.confirm_action(q): return # Disable source host unless no-disable param is used if not options.dry_run and not options.no_disable: nc.disable_host(source) dry_run_txt = 'DRY_RUN: ' if options.dry_run else '' instances = nc.get_all_instances(search_opts=search_opts) count = 0 for i in instances: state = getattr(i, 'OS-EXT-STS:vm_state') state_task = getattr(i, 'OS-EXT-STS:task_state') if state_task: logger.debug('=> instance running task %s, dropping migrate', state_task) continue logger.debug('=> %smigrate %s to %s', dry_run_txt, i.name, target) if (state == 'active' or state == 'paused') and not options.dry_run: i.live_migrate(host=target) time.sleep(options.sleep) elif state == 'stopped' and not options.dry_run: i.migrate(host=target) time.sleep(options.sleep) # elif state == 'suspended' and not options.dry_run: # i.resume() # time.sleep(2) # i.pause() # time.sleep(5) # i.live_migrate(host=target) # time.sleep(options.sleep) elif not options.dry_run: logger.debug('=> dropping migrate of %s unknown state %s', i.name, state) count += 1 if options.limit and count >= options.limit: logger.debug('=> number of instances reached limit %s', options.limit) break
def action_evacuate(): source_host = nc.get_host(source) if source_host.state != 'down': himutils.sys_error('Evacuate failed. Source host need to be down! Use migrate') # Check that there are other valid hosts in the same aggregate hosts = nc.get_aggregate_hosts(options.aggregate) found_enabled = list() for host in hosts: if host.hypervisor_hostname == source: continue if host.status == 'enabled' and host.state == 'up': found_enabled.append(host.hypervisor_hostname) if not found_enabled: himutils.sys_error('Evacuate failed. No valid host in aggregate %s' % options.aggregate) logger.debug('=> valid host found %s', ", ".join(found_enabled)) # Interactive question q = 'Evacuate all instances from %s to other hosts' % source if not himutils.confirm_action(q): return instances = nc.get_all_instances(search_opts=search_opts) dry_run_txt = 'DRY_RUN: ' if options.dry_run else '' count = 0 for i in instances: state = getattr(i, 'OS-EXT-STS:vm_state') logger.debug('=> %sevacuate %s', dry_run_txt, i.name) if state == 'active' and not options.dry_run: i.evacuate() time.sleep(options.sleep) elif state == 'stopped' and not options.dry_run: i.evacuate() time.sleep(options.sleep) elif not options.dry_run: logger.debug('=> dropping evacuate of %s unknown state %s', i.name, state) count += 1 if options.limit and count > options.limit: logger.debug('=> number of instances reached limit %s', options.limit) break
def set_access(image_action): if image_action == 'revoke' and options.project_by_id: project_id = options.project else: project = kc.get_project_by_name(options.project) if not project: utils.sys_error('Unknown project {}'.format(options.project)) project_id = project.id # Grant based on tags, name or type tags = get_tags(names=True) tag_str = 'all tags' if not tags else '[' + ', '.join(tags) + ']' if not options.force and not utils.confirm_action( '{} access to shared images matching {}'.format( image_action.capitalize(), tag_str)): return filters = {'status': 'active', 'tag': tags, 'visibility': 'shared'} kc.debug_log('filter: {}'.format(filters)) images = gc.get_images(filters=filters) for image in images: gc.set_image_access(image_id=image.id, project_id=project_id, action=image_action) printer.output_msg('{} access to image {} for project {}'.format( image_action.capitalize(), image.name, options.project))
def action_stop_instance(): msg = 'Remember to purge db with state.py first! Continue?' if not options.dry_run and not utils.confirm_action(msg): return state = utils.get_client(State, options, logger) for region in regions: nova = utils.get_client(Nova, options, logger, region) instances = nova.get_instances(options.aggregate) for i in instances: instance_data = i.to_dict().copy() instance_data['region'] = region instance_data['aggregate'] = options.aggregate instance_data['instance_id'] = i.id instance_data.pop('created', None) # not instance created, but db instance = state.get_first(Instance, instance_id=i.id) if instance is None: # add to db if not found instance = Instance.create(instance_data) #pylint: disable=E1101 state.add(instance) nova.stop_instance(i) state.close()
def action_list(): # pylint: disable=W0612 blacklist, whitelist, notify = load_config() for region in regions: nova = utils.get_client(Nova, options, logger, region) neutron = utils.get_client(Neutron, options, logger, region) rules = neutron.get_security_group_rules(1000) question = ( "Are you sure you will check {} security group rules in {}?". format(len(rules), region)) if not options.assume_yes and not utils.confirm_action(question): return printer.output_dict( {'header': 'Rules in {} (project, port, ip)'.format(region)}) for rule in rules: if is_whitelist(rule, whitelist): continue if is_blacklist(rule, blacklist): continue sec_group = neutron.get_security_group(rule['security_group_id']) if not rule_in_use(sec_group, nova): continue # check if project exists project = kc.get_by_id('project', rule['project_id']) if not project: kc.debug_log('could not find project {}'.format( rule['project_id'])) continue output = { '0': project.name, '1': "{}-{}".format(rule['port_range_min'], rule['port_range_max']), '2': rule['remote_ip_prefix'] } printer.output_dict(output, one_line=True)
def action_delete(): days = 90 question = 'Delete demo instances older than {} days?'.format(days) if not options.force and not utils.confirm_action(question): return projects = kc.get_projects(type='demo') logfile = 'logs/demo-logs/deleted_instances/deleted-expired-demo-instances-{}.log'.format( date.today().isoformat()) for region in regions: for project in projects: nc = utils.get_client(Nova, options, logger, region) instances = nc.get_project_instances(project_id=project.id) for instance in instances: created = utils.get_date(instance.created, None, '%Y-%m-%dT%H:%M:%SZ') active_days = (date.today() - created).days kc.debug_log('Found instance {} for user {}'.format( instance.id, project.admin)) if int(active_days) >= days: nc.delete_instance(instance) if not options.dry_run: utils.append_to_logfile(logfile, "deleted:", project.name, instance.name, "active for:", active_days)
def action_rename(): if not ksclient.is_valid_user(email=options.old, domain=domain): print "%s is not a valid user. Please check your spelling or case." % options.old sys.exit(1) obj = ksclient.get_user_objects(email=options.old, domain=domain) print obj['projects'] new_demo_project = ksclient.get_project_name(options.new) old_demo_project = ksclient.get_project_name(options.old) print "\nYou are about to rename user with email %s to %s" % (options.old, options.new) print "\nWhen a user changes affilation we need to change the following:" print " * Delete %s-group if it exists" % options.new print " * Delete %s api user if it exists" % options.new.lower() print " * Delete %s dataporten user if it exists" % options.new.lower() print " * Delete all personal project for user %s" % options.new.lower() print " * Delete %s demo project" % new_demo_project print " * Delete %s instances in demo project if it exists" % new_demo_project print " * Rename group from %s-group to %s-group" % (options.old, options.new) print " * Rename api user from %s to %s" % (options.old.lower(), options.new.lower()) print " * Rename demo project from %s to %s" % (old_demo_project, new_demo_project) print " * Delete old dataporten user %s" % (options.old) question = "\nAre you sure you will continue" if not himutils.confirm_action(question): return print 'Please wait...' ksclient.remove_user(email=options.new, domain=domain, dry_run=options.dry_run) ksclient.rename_user(new_email=options.new, old_email=options.old, domain=domain, dry_run=options.dry_run)
def action_delete(): status_id = options.status_id if not himutils.confirm_action('Are you sure you want to delete status message with id %s' % status_id): return status.delete(status_id)
def action_delete(): question = 'Delete project %s and all resources' % options.project if not options.force and not himutils.confirm_action(question): return ksclient.delete_project(options.project)
def action_delete(): question = 'Delete project %s and all resources' % options.project if not options.force and not himutils.confirm_action(question): return ksclient.delete_project(options.project, domain=options.domain)
def confirm_publish(final_msg): print('The following message will be published: %s' % final_msg) if not himutils.confirm_action('Are you sure you want to publish?'): sys.exit(1)
def action_create(): if not ksclient.is_valid_user(options.admin, options.domain) and options.type == 'personal': himutils.sys_error('not valid user', 1) quota = himutils.load_config('config/quotas/%s.yaml' % options.quota) if options.quota and not quota: himutils.sys_error('Could not find quota in config/quotas/%s.yaml' % options.quota) test = 1 if options.type == 'test' else 0 if options.enddate: try: enddate = datetime.strptime(options.enddate, '%d.%m.%Y').date() except ValueError: himutils.sys_error('date format DD.MM.YYYY not valid for %s' % options.enddate, 1) else: enddate = None createdate = datetime.today() if not options.force: print 'Project name: %s\nAdmin: %s\nType: %s\nEnd date: %s\nQuota: %s\nRT: %s' \ % (options.project, options.admin.lower(), options.type, str(enddate), options.quota, options.rt) if not himutils.confirm_action('Are you sure you want to create this project?'): himutils.sys_error('Aborted', 1) project = ksclient.create_project(project_name=options.project, admin=options.admin.lower(), test=test, type=options.type, description=options.desc, enddate=str(enddate), createdate=createdate.isoformat(), quota=options.quota, rt=options.rt) if not ksclient.is_valid_user(options.admin, options.domain): himutils.sys_error('WARNING: "%s" is not a valid user.' % options.admin, 0) if not project: himutils.sys_error('Failed creating %s' % options.project, 1) else: output = Keystone.get_dict(project) output['header'] = "Show information for %s" % options.project printer.output_dict(output) # Quotas for region in regions: novaclient = Nova(options.config, debug=options.debug, log=logger, region=region) cinderclient = Cinder(options.config, debug=options.debug, log=logger, region=region) neutronclient = Neutron(options.config, debug=options.debug, log=logger, region=region) cinderclient.set_dry_run(options.dry_run) novaclient.set_dry_run(options.dry_run) neutronclient.set_dry_run(options.dry_run) project_id = Keystone.get_attr(project, 'id') if quota and 'cinder' in quota and project: cinderclient.update_quota(project_id=project_id, updates=quota['cinder']) if quota and 'nova' in quota and project: novaclient.update_quota(project_id=project_id, updates=quota['nova']) if quota and 'neutron' in quota and project: neutronclient.update_quota(project_id=project_id, updates=quota['neutron']) if options.mail: mail = Mail(options.config, debug=options.debug) mail.set_dry_run(options.dry_run) if options.rt is None: himutils.sys_error('--rt parameter is missing.') else: mapping = dict(project_name=options.project, admin=options.admin.lower(), quota=options.quota, end_date=str(enddate)) subject = 'UH-IaaS: Project %s has been created' % options.project body_content = himutils.load_template(inputfile=project_msg_file, mapping=mapping) if not body_content: himutils.sys_error('ERROR! Could not find and parse mail body in \ %s' % options.msg) mime = mail.rt_mail(options.rt, subject, body_content) mail.send_mail('*****@*****.**', mime)
def confirm_publish(final_msg): print('The following message will be published: %s' % final_msg) if not himutils.confirm_action('Are you sure you want to publish?'): sys.exit(1)