Esempio n. 1
0
 def cfgGet(self, section, field):
     mapping = {
         'cleanup/max-images-per-flavor': {
             'default': 1
         },
         'cleanup/max-image-age-hours': {
             'default': 24 * 31
         },
         'cleanup/min-image-age-hours': {
             'default': 24
         },
         'cleanup/azure-storage-resourcegroup': {
             'default': 'openqa-upload'
         },
         'cleanup/azure-storage-account-name': {
             'default': 'openqa'
         },
         'cleanup/ec2-max-snapshot-age-days': {
             'default': -1
         },
     }
     key = '/'.join([section, field])
     if key not in mapping:
         raise LookupError("Missing {} in mapping list".format(key))
     e = mapping[key]
     namespace_section = '{}.namespace.{}'.format(section, self.__namespace)
     cfg = ConfigFile()
     return type(e['default'])(cfg.get([namespace_section, field],
                                       cfg.get([section, field],
                                               e['default'])))
Esempio n. 2
0
def send_cluster_notification(namespace, clusters):
    cfg = ConfigFile()
    cfg_path = ['notify.cluster.namespace.{}'.format(namespace), 'to']
    if not cfg.has('notify') or not cfg.has(cfg_path):
        return
    if len(clusters):
        clusters_str = ' '.join([str(cluster) for cluster in clusters])
        logger.debug("Full clusters list - %s", clusters_str)
        send_mail("EC2 clusters found",
                  clusters_str,
                  receiver_email=cfg.get(cfg_path))
Esempio n. 3
0
def list_clusters():
    cfg = ConfigFile()
    if cfg.has('clusters'):
        for vault_namespace in cfg.getList(['clusters', 'namespaces'], ['']):
            try:
                clusters = EC2(vault_namespace).all_clusters()
                logger.info("%d clusters found", len(clusters))
                send_cluster_notification(vault_namespace, clusters)
            except Exception as e:
                logger.exception("[{}] List clusters failed!".format(vault_namespace))
                send_mail('{} on List clusters in [{}]'.format(
                    type(e).__name__, vault_namespace), traceback.format_exc())
Esempio n. 4
0
def send_mail(subject, message, receiver_email=None):
    cfg = ConfigFile()
    if not cfg.has('notify'):
        return

    smtp_server = cfg.get(['notify', 'smtp'])
    port = cfg.get(['notify', 'smtp-port'], 25)
    sender_email = cfg.get(['notify', 'from'])
    if receiver_email is None:
        receiver_email = cfg.get(['notify', 'to'])
    email = '''\
Subject: [Openqa-Cloud-Watch] {subject}
From: {_from}
To: {_to}

{message}
'''.format(subject=subject,
           _from=sender_email,
           _to=receiver_email,
           message=message)
    logger.info("Send Email To:'%s' Subject:'[Openqa-Cloud-Watch] %s'",
                receiver_email, subject)
    server = smtplib.SMTP(smtp_server, port)
    server.ehlo()
    server.sendmail(sender_email, receiver_email.split(','), email)
Esempio n. 5
0
def send_leftover_notification():
    cfg = ConfigFile()
    if not cfg.has('notify'):
        return
    o = Instance.objects
    o = o.filter(
        active=True,
        csp_info__icontains='openqa_created_by',
        age__gt=timedelta(hours=int(cfg.get(['notify', 'age-hours'], 12))))

    if o.filter(notified=False).count() == 0:
        return

    subject = cfg.get(['notify', 'subject'], 'CSP left overs')
    body_prefix = "Message from {url}\n\n".format(url=build_absolute_uri())
    send_mail(subject, body_prefix + draw_instance_table(o))

    # Handle namespaces
    namespaces = list(dict.fromkeys([i.vault_namespace for i in o]))
    for namespace in namespaces:
        cfg_path = ['notify.namespace.{}'.format(namespace), 'to']
        if not cfg.has(cfg_path):
            continue
        receiver_email = cfg.get(cfg_path)
        namespace_objects = o.filter(vault_namespace=namespace)
        if namespace_objects.filter(notified=False).count() == 0:
            continue
        send_mail(subject,
                  body_prefix + draw_instance_table(namespace_objects),
                  receiver_email=receiver_email)

    o.update(notified=True)
Esempio n. 6
0
def auto_delete_instances():
    cfg = ConfigFile()
    for vault_namespace in cfg.getList(['vault', 'namespaces'], ['']):
        o = Instance.objects
        o = o.filter(state=StateChoice.ACTIVE, vault_namespace=vault_namespace,
                     ttl__gt=timedelta(0), age__gte=F('ttl'), csp_info__icontains='openqa_created_by')
        email_text = set()
        for i in o:
            logger.info("[{}][{}] TTL expire for instance {}".format(i.provider, i.vault_namespace, i.instance_id))
            try:
                delete_instance(i)
            except Exception:
                msg = "[{}][{}] Deleting instance ({}) failed".format(i.provider, i.vault_namespace, i.instance_id)
                logger.exception(msg)
                email_text.add("{}\n\n{}".format(msg, traceback.format_exc()))

        if len(email_text) > 0:
            send_mail('[{}] Error on auto deleting instance(s)'.format(vault_namespace),
                      "\n{}\n".format('#'*79).join(email_text))
Esempio n. 7
0
def update_run():
    '''
    Each update is using Instance.active to mark the model is still availalbe on CSP.
    Instance.state is used to reflect the "local" state, e.g. if someone triggered a delete, the
    state will moved to DELETING. If the instance is gone from CSP, the state will set to DELETED.
    '''
    global __running, __last_update
    __running = True
    cfg = ConfigFile()
    max_retries = 3
    error_occured = False

    for vault_namespace in cfg.getList(['vault', 'namespaces'], ['']):
        for provider in cfg.getList(['vault.namespace.{}'.format(vault_namespace), 'providers'],
                                    ['ec2', 'azure', 'gce']):
            logger.info("Check provider %s in vault_namespace %s", provider, vault_namespace)
            email_text = set()
            for n in range(max_retries):
                try:
                    _update_provider(provider, vault_namespace)
                except Exception:
                    logger.exception("Update failed for {} in namespace {}".format(provider, vault_namespace))
                    email_text.add(traceback.format_exc())
                    time.sleep(5)
                else:
                    break
            else:
                error_occured = True
                send_mail('Error on update {} in namespace {}'.format(provider, vault_namespace),
                          "\n{}\n".format('#'*79).join(email_text))

    auto_delete_instances()
    send_leftover_notification()
    __running = False
    if not error_occured:
        __last_update = datetime.now(timezone.utc)

    if not getScheduler().get_job('update_db'):
        init_cron()
Esempio n. 8
0
def _update_provider(name, vault_namespace):
    cfg = ConfigFile()

    if 'azure' in name:
        instances = Azure(vault_namespace).list_resource_groups()
        instances = [azure_to_local_instance(i, vault_namespace) for i in instances]
        logger.info("Got %d resources groups from Azure", len(instances))
        sync_csp_to_local_db(instances, ProviderChoice.AZURE, vault_namespace)

    if 'ec2' in name:
        instances = []
        for region in cfg.getList(['ec2', 'regions'], EC2(vault_namespace).all_regions()):
            instances_csp = EC2(vault_namespace).list_instances(region=region)
            instances += [ec2_to_local_instance(i, vault_namespace, region) for i in instances_csp]
            logger.info("Got %d instances from EC2 in region %s", len(instances), region)
        sync_csp_to_local_db(instances, ProviderChoice.EC2, vault_namespace)

    if 'gce' in name:
        instances = GCE(vault_namespace).list_all_instances()
        instances = [gce_to_local_instance(i, vault_namespace) for i in instances]
        logger.info("Got %d instances from GCE", len(instances))
        sync_csp_to_local_db(instances, ProviderChoice.GCE, vault_namespace)
Esempio n. 9
0
 def getData(self, name=None):
     use_file_cache = ConfigFile().getBoolean(['vault', 'use-file-cache'])
     if self.auth_json is None and use_file_cache:
         self.auth_json = self.loadAuthCache()
     if self.isExpired():
         self.auth_json = self.getCredentials()
         expire = datetime.today() + timedelta(seconds=self.auth_json['lease_duration'])
         self.auth_json['auth_expire'] = expire.isoformat()
         if expire > self.client_token_expire:
             self.renewClientToken(self.auth_json['lease_duration'])
         if use_file_cache:
             self.saveAuthCache()
     if name is None:
         return self.auth_json['data']
     return self.auth_json['data'][name]
Esempio n. 10
0
 def __init__(self, vault_namespace):
     cfg = ConfigFile()
     self.url = cfg.get(['vault', 'url'])
     self.user = cfg.get(['vault', 'user'])
     self.namespace = vault_namespace
     self.password = cfg.get(['vault', 'password'])
     self.certificate_dir = cfg.get(['vault', 'cert_dir'], '/etc/ssl/certs')
     self.auth_json = None
     self.client_token = None
     self.client_token_expire = None
Esempio n. 11
0
 def __init__(self, vault_namespace):
     cfg = ConfigFile()
     self.url = cfg.get(['vault', 'url'])
     self.user = cfg.get(['vault', 'user'])
     self.namespace = vault_namespace
     self.password = cfg.get(['vault', 'password'])
     self.certificate_dir = cfg.get(['vault', 'cert_dir'], '/etc/ssl/certs')
     if cfg.getBoolean(['vault', 'use-file-cache'
                        ]) and self._getAuthCacheFile().exists():
         logger.info('Loading cached credentials')
         self.auth_json = self.loadAuthCache()
     else:
         self.auth_json = None
     self.client_token = None
     self.client_token_expire = None
Esempio n. 12
0
def cleanup_run():
    cfg = ConfigFile()
    if cfg.has('cleanup'):
        for vault_namespace in cfg.getList(['cleanup', 'namespaces'], cfg.getList(['vault', 'namespaces'], [''])):
            try:
                providers = cfg.getList(['vault.namespace.{}'.format(vault_namespace), 'providers'],
                                        ['ec2', 'azure', 'gce'])
                logger.debug("[{}] Run cleanup for {}".format(vault_namespace, ','.join(providers)))
                if 'azure' in providers:
                    Azure(vault_namespace).cleanup_all()

                if 'ec2' in providers:
                    EC2(vault_namespace).cleanup_all()

                if 'gce' in providers:
                    GCE(vault_namespace).cleanup_all()

            except Exception as e:
                logger.exception("[{}] Cleanup failed!".format(vault_namespace))
                send_mail('{} on Cleanup in [{}]'.format(type(e).__name__, vault_namespace), traceback.format_exc())
Esempio n. 13
0
 def __init__(self, namespace):
     self.__namespace = namespace
     self.dry_run = ConfigFile().getBoolean(['default', 'dry_run'], False)
     self.logger = logging.getLogger(self.__module__)
Esempio n. 14
0
 def __init__(self, namespace):
     self.__namespace = namespace
     self.dry_run = ConfigFile().getBoolean(['default', 'dry_run'], False)
Esempio n. 15
0
 def renew(self):
     if ConfigFile().getBoolean(['vault', 'use-file-cache'
                                 ]) and self._getAuthCacheFile().exists():
         self._getAuthCacheFile().unlink()
     self.revoke()
     self.getData()