import os
from collections import OrderedDict
-from datetime import datetime
+import datetime
+
+import yaml
+from dateutil import parser as date_parser
from os_connector import OpenStackActions
from logger import logger
+from helpers import get_lifetime_delta
+
try:
import prehooks
except ImportError:
ignorelist_file=None):
self.ignorelist_uuids = []
- if ignorelist_file is not None and os.path.exists(ignorelist_file):
- with open(ignorelist_file) as f:
- for line in f.readlines():
- if line and not line.startswith("#"):
- self.ignorelist_uuids.append(line.split(" ")[0])
+ if ignorelist_file is not None:
+ if os.path.exists(ignorelist_file):
+ with open(ignorelist_file) as f:
+ for line in f.readlines():
+ if line and not line.startswith("#"):
+ self.ignorelist_uuids.append(line.split(" ")[0])
+ else:
+ logger.error("ERROR: ignorelist file is passed but not found! "
+ "(could be working dir issue")
+ raise AttributeError
+ self.os_user = os_user
self.os_conn = OpenStackActions(
auth_url=os_auth_url,
user=os_user,
'routers': routers,
'subnets': subnets}
+ def get_keypairs(self):
+ return self.os_conn.get_keypairs()
+
def get_servers(self):
return self.os_conn.get_servers()
self.cleanup_stack_parallel(uuid)
else:
logger.info("Can't find anything with is {}".format(uuid))
+
+ def get_user_keypair_keeplist(self, raise_exc=True):
+ file_exists = os.path.exists('keypair_keeplist.yml')
+ if not file_exists:
+ raise AssertionError("keypair_keeplist not found, "
+ "too dangerous to proceed")
+ with open("keypair_keeplist.yml") as f:
+ keeplist = yaml.safe_load(f)
+ current_user_keeplist = keeplist.get(self.os_user, [])
+ if not current_user_keeplist:
+ if raise_exc:
+ raise AssertionError(
+ "keeplist for user {} empty, too dangerous "
+ "for cleanup operation".format(self.os_user))
+ else:
+ logger.warning("keeplist for user {} empty; cleanup operation "
+ "will be unavailable".format(self.os_user))
+ return current_user_keeplist
+
+ def search_keypairs(self, name='', fingerprint='', lifetime=''):
+ current_user_keeplist = self.get_user_keypair_keeplist(raise_exc=False)
+
+ keypairs = self.get_keypairs()
+ result = []
+ now = datetime.datetime.utcnow()
+
+ def check_gen_req(name, keypair_name):
+ if name == "DETECT_128":
+ return len(keypair_name) == 128
+ return name in keypair_name
+
+ for keypair in keypairs:
+ if keypair.name in current_user_keeplist:
+ logger.info("IGNORE > keypair {}".format(keypair.name))
+ continue
+ if check_gen_req(name,
+ keypair.name) and fingerprint in keypair.fingerprint:
+ if lifetime:
+ lifetime_delta = get_lifetime_delta(lifetime)
+ if now - date_parser.parse(
+ keypair.created_at) > lifetime_delta:
+ result.append(keypair)
+ else:
+ result.append(keypair)
+ return result
+
+ def cleanup_keypairs(self, name='', fingerprint='', lifetime=''):
+ keypairs_to_delete = self.search_keypairs(name, fingerprint, lifetime)
+ # use get user keypair keeplist to stop script if there is no keeplist
+ self.get_user_keypair_keeplist(raise_exc=True)
+ for keypair in keypairs_to_delete:
+ logger.info("Deleting keypair {}".format(keypair.name))
+ keypair.delete()
+import datetime
import signal
import time
predicate_args,
predicate_kwargs,
timeout))
+
+
+def get_lifetime_delta(lifetime):
+ multipliers = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
+ if lifetime[-1] not in multipliers:
+ raise ValueError(
+ 'Value should end with '
+ 'one of "{}", got "{}"'.format(
+ " ".join(multipliers.keys()), lifetime
+ ))
+ num = int(lifetime[:-1])
+ mul = lifetime[-1]
+ return datetime.timedelta(seconds=num*multipliers[mul])
3fb4af2b-40d4-4ec3-88a0-17c3edd8ed67 # dstremkouski-k8s-node02
1589214e-43bf-4d57-80ac-68b28030c536 # sre-monitoring
5b222dd9-aeb9-42bd-8fac-e8f3874238d9 # dench-desktop
+d6c676ff-d47d-4d64-8624-977b4d1ff27b # sre-team-infra
+64b25fd1-d59f-4eb0-a732-cc500fd87ba1 # pkgs-ci-xenial-slave01
+a680c184-60f0-4ac8-9c0d-a6cc7a083bb1 # model-manager-prod
# Networks
0563f790-92a3-4c92-ab41-74478442a75e # physnet1-402
b7b8b2e1-fb2e-4edb-9540-500363155fe3 # cvp-internal
5d4a2029-6c32-4bee-89dc-855829cc2233 # physnet1-432
c11bf78a-de07-4e67-8047-a28b247c27bb # sre-internal
bf6b85a1-39db-4582-b0d1-f4291dddb9cf # public
+07545b24-decb-4b19-848e-30937aa85359 # sre-team-default-internal-net
+30e7b0b7-4fab-4dbb-bc38-4c64d489d3df # pkgs-ci-xenial-slave-net
+c3799996-dc8e-4477-a309-09ea6dd71946 # public
+af8a9bba-627f-4b79-9416-8595897cb5e2 # model-manager-net
# Routers
d92fc584-371b-4c0b-aa85-9c5c49292129 # sre-router
808a47c2-7ee4-46c2-b232-b625c70bd5d7 # vdrok-unittest
+1c7803d2-0fcc-4084-9a89-e4b133270a77 # model-manager-router
+4b78d573-2435-429b-8e9d-5f4ca88f2271 # pkgs-ci-xenial-slave-router
+49851843-4a8a-411b-8d62-c47e536f9902 # sre-team-default-router
# Volumes
83bada1a-3a04-413f-b3ef-d0f26adf69e2 # dstremkouski-convert-qcow2-raw
0d0665c2-c684-4a66-a224-72462ccb016d # dstremkouski-500G-stripe
d0eb9a28-8ea1-4728-9fcc-5e89d1fd773d # dstremkouski-500G
d32349f4-74eb-4acb-a7a4-b9ae32029000 # windows-vw-jump
48a15d0c-5c48-45dc-b8db-13462239278c # sre-monitoring
+5eb4a3c6-4dc3-437e-9ac5-0b15a1ffe873 # pkgs-ci-xenial-slave01 as /dev/vda
+36a7a3a0-0c0e-4999-a793-d95003025100 # model-manager-prod-11092019
# Subnets
+04999e63-a03f-4916-9923-01eb2e71a362 # model-manager-subnet
+a5f29252-f0c0-4bff-887a-44217bd8c151 # pkgs-ci-xenial-slave-subnet
+d83983b6-16b6-4a72-a6df-71583bbd1f88 # sre-team-default-internal-subnet
4e248805-d684-4411-bb3f-143ec8da5bad # cvp-subnet-internal-2
7d7e65ba-d6cf-458f-b963-50614fac5e00 # baremetal-subnet
0822b2c1-4676-46f1-a382-54d3c9ab1458 # physnet1-432-subnet
--- /dev/null
+# mentioned here keypairs will never be deleted by cleaner; add your keys if needed here
+# username:
+# - keypair_name
+# - keypair_name
+vkhlyunev:
+ - jenkins-patching-ci # US
+ - vkhlyunev # US,EU
+maintenance-ci-robot:
+ - maintenance-ci-public-key
+ - system-key-8133
+drivetrain-jenkins:
+ - oscore-devcloud-env-ssh-public
+ - jenkins-mk
+ - k8s-helm-aio
+ - mcp-scale-jenkins
+ - mcpng2cmp
+ - system-key-8133
+ - system_key_8133
+ - mosk-ga
+ - scale-team-heat-mcp-2
\ No newline at end of file
from __future__ import unicode_literals
-import time
-
from cinderclient.exceptions import NotFound
from cinderclient.v2.client import Client as CinderClient
from heatclient.v1.client import Client as HeatClient
if f_ip_data['floating_ip_address'] == floating_ip:
return f_ip_data['id']
+ def get_keypairs(self):
+ keypairs = self.nova.keypairs.list()
+ resp = []
+ for keypair in keypairs:
+ resp.append(self.nova.keypairs.get(keypair.name))
+ return resp
+
+ def get_one_keypair(self, name):
+ return self.nova.keypairs.get(name)
+
def get_ports(self):
response = self.neutron.list_ports()
ports = response['ports']
return True
return False
- def check_subnet_exists(self, subnet_uuid):
- resp = self.neutron.list_subnets(id=subnet_uuid)['subnets']
- if resp:
- return True
- return False
-
def check_any_network_exists(self, uuids):
return any(
[self.check_network_exists(uuid) for uuid in uuids]
import argparse
+from dateutil import parser as date_parser
import os
import sys
+
from prettytable import PrettyTable
from cleaner import Cleaner
from logger import logger
+
try:
import prehooks
except ImportError:
print table
+def do_search_keypair(name='', fingerprint='', lifetime=''):
+ keypairs = cleaner.search_keypairs(name, fingerprint, lifetime)
+ table = PrettyTable()
+ table.field_names = ['name', 'created_at', 'fingerprint']
+ table.align = 'l'
+ for value in sorted(keypairs, reverse=True, key=lambda x: date_parser.parse(x.created_at)):
+ table.add_row([value.name, value.created_at, value.fingerprint])
+ print table
+
+
parser = argparse.ArgumentParser()
parser.add_argument('--os-auth-url', type=str)
parser.add_argument('--os-username', type=str)
help="allowed: stack, misc")
cleanup_subparser.add_argument('ids', nargs='*', type=str,
help="uuids or names, error if name duplicates")
-# cleanup_subparser.add_argument('--force', '-f', default=False,
-# action='store_true')
+
+cleanup_subparser.add_argument('--name',
+ '-n',
+ type=str,
+ help='Search resources that only contains given name;'
+ 'usable for: search non-stack keypair operation; '
+ 'for keypair there is pre-defined DETECT_128 for '
+ '128char generated names',
+ default='')
+cleanup_subparser.add_argument('--lifetime',
+ '-l',
+ type=str,
+ help='Usable for keypairs only; search/cleanuo keypairs only '
+ 'older than given timeframe; '
+ '30d - older than 30 days',
+ default='')
+cleanup_subparser.add_argument('--fingerprint',
+ type=str,
+ help='Usable for keypairs only; Search resources '
+ 'that only contains given fingerprint',
+ default='')
+
search_subparser = subparsers.add_parser('search')
-search_subparser.add_argument('--name', '-n', type=str,
- help='part of name to search for',
- default='')
+search_subparser.add_argument('resource_type', type=str,
+ help="allowed: misc, keypair")
+
search_subparser.add_argument('--only-uuids', '-i',
help='print only uuids for chain xargs call',
default=False, action='store_true')
+search_subparser.add_argument('--name',
+ '-n',
+ type=str,
+ help='Search resources that only contains given name;'
+ 'usable for: search non-stack keypair operation; '
+ 'for keypair there is pre-defined DETECT_128 for '
+ '128char generated names',
+ default='')
+search_subparser.add_argument('--lifetime',
+ '-l',
+ type=str,
+ help='Usable for keypairs only; search/cleanuo keypairs only '
+ 'older than given timeframe; '
+ '30d - older than 30 days',
+ default='')
+search_subparser.add_argument('--fingerprint',
+ type=str,
+ help='Usable for keypairs only; Search resources '
+ 'that only contains given fingerprint',
+ default='')
# args = parser.parse_args("cleanup stack bm-cicd-pike-ovs-maas".split(" "))
# args = parser.parse_args("search -i -n bm-cicd-pike-ovs-maas".split(" "))
# args = parser.parse_args("search".split(" "))
# debug_args = "cleanup stack heat-cicd-queens-dvr-sl"
-# debug_args = "search -n vkhlyunev"
+# debug_args = "search non-stack -n vkhlyunev"
+# debug_args = "search non-stack"
+# debug_args = "search keypair -l 1d"
+# debug_args = "cleanup keypair --name test -l 1m"
# args = parser.parse_args(debug_args.split(" "))
args = parser.parse_args()
'OS_USER_DOMAIN_NAME')
for validated_item in auth_data:
- if not auth_data[validated_item]:
- logger.error("Parameter {} NOT defined.".format(validated_item))
- sys.exit(124)
+ if not auth_data[validated_item]:
+ logger.error("Parameter {} NOT defined.".format(validated_item))
+ sys.exit(124)
cleaner = Cleaner(os_auth_url=auth_data['auth_url'],
os_user=auth_data['username'],
os_id))
else:
logger.info("Stack not found, nothing to delete")
- if args.resource_type == "misc":
+ elif args.resource_type == "misc":
os_ids = args.ids
if not os_ids:
data = sys.stdin.read()
if os_id:
logger.info("Processing {}...".format(os_id))
cleaner.process_resource(os_id)
+ elif args.resource_type == "keypair":
+ cleaner.cleanup_keypairs(args.name, args.fingerprint, args.lifetime)
+
elif args.action == "search":
- do_search(args.name, args.only_uuids)
+ if args.resource_type == "non-stack":
+ do_search(args.name, args.only_uuids)
+ elif args.resource_type == "keypair":
+ do_search_keypair(args.name, args.fingerprint, args.lifetime)
+