Esempio n. 1
0
def console_report():
    """Runs a report from the cli."""

    args = parser.parse_args()
    conf = config.load(args.config_file)
    logger.setLevel(LOG_LEVELS.get(args.log_level.lower(), 'info'))

    manager = ClientManager(**conf.get('auth_kwargs', {}))
    ceilometer = manager.get_ceilometer()

    if args.mtd:
        start, stop = utils.mtd_range()
    elif args.today:
        start, stop = utils.today_range()
    elif args.last_hour:
        start, stop = utils.last_hour_range()
    else:
        start, stop = utils.mtd_range()

    r = Report(
        ceilometer,
        args.definition_filename,
        args.csv_filename,
        start=start,
        stop=stop
    )
    r.run()
Esempio n. 2
0
def console_report():
    """Runs a report from the cli."""
    args = report_parser.parse_args()
    conf = config.load(args.config_file)
    logger.setLevel(LOG_LEVELS.get(args.log_level.lower(), 'info'))

    manager = ClientManager(**conf.get('auth_kwargs', {}))
    ceilometer = manager.get_ceilometer()

    out = output.Stream() if args.use_stdout else None

    if args.mtd:
        start, stop = utils.mtd_range()
        out = out or output.Mtd(args.output_directory, start, stop)
    elif args.today:
        start, stop = utils.today_range()
        out = out or output.Daily(args.output_directory, start, stop)
    elif args.last_hour:
        start, stop = utils.last_hour_range()
        out = out or output.Hourly(args.output_directory, start, stop)

    # If stop is provided, check for start
    elif args.stop:
        if not args.start:
            raise Exception('Provide --start if also using --stop')
        start = args.start
        stop = args.stop
        out = out or output.Other(args.output_directory, start, stop)

    # If start is provided, check for stop. If stop not provided,
    # default to now
    elif args.start:
        start = args.start
        _, now = utils.mtd_range()
        stop = args.stop or now
        out = out or output.Other(args.output_directory, start, stop)

    # Default to month to date
    else:
        start, stop = utils.mtd_range()
        out = out or output.Mtd(args.output_directory, start, stop)
    try:
        p_start = time.time()
        r = Report(
            ceilometer,
            args.definition_filename,
            out,
            start=start,
            stop=stop,
            max_samples=args.max_samples
        )
        r.run()
        logger.debug("Finished in {} seconds".format(time.time() - p_start))
    finally:
        out.close()

    if args.show_tags:
        print tag.all()
Esempio n. 3
0
def console_summary():
    """Summarizes a csv report."""
    args = summary_parser.parse_args()
    conf = config.load(args.config_file)
    logger.setLevel(LOG_LEVELS.get(args.log_level.lower(), 'info'))
    clientmanager = ClientManager(**conf.get('auth_kwargs', {}))
    Summary(
        domain_client=clientmanager.get_domain(),
        input_file=args.csv_file,
        project_id_column=args.project_id_field,
        cost_column=args.cost_field,
        group_by=args.group_by
    ).output()
Esempio n. 4
0
def console_licensing():
    """Summarizes a csv report."""
    from licensing import Licensing
    from args.licensing import parser as licensing_parser
    from domain_cache import set_domain_client
    args = licensing_parser.parse_args()
    conf = config.load(args.config_file)
    logger.setLevel(LOG_LEVELS.get(args.log_level.lower(), 'info'))
    clientmanager = ClientManager(**conf.get('auth_kwargs', {}))
    set_domain_client(clientmanager.get_domain())
    Licensing(
        definition_file=args.definition_file,
        input_file=args.csv_file
    ).output()
Esempio n. 5
0
def test():
    logger.info("Starting test...")
    args = argparser.parse_args()
    conf = config.load(args.config_file)
    auth_kwargs = config.get('auth_kwargs', {})
    clients = ClientManager(**config.get('auth_kwargs', {}))
    volume_delete(clients, conf)
Esempio n. 6
0
    def __init__(self):
        """
        This is what holds the decryption keys for the hashes.
        It's really important that this doesn't change during
        a run, or you'll get different outputs.

        :param key: The shared key used for 2 way encryption.
        :type key: 16 character length string.
        :param iv: The initialization vector for reversing a hash.
        :type iv: binary number in bytes
        """
        self.__crypto_info = {
            'key': "Sixteen byte key",
            'iv': None #This gets populated on first use.
        }

        """
        This is the big map of users. The key is a representation
        of its role assignment (domain, project, role). The value
        is a credentials object.
        """
        self.__users = {}
        """
        These credentials are so that we can create anything we
        need to in keystone. They must be admin level credentials.

        """
        env_vars_default = {
            'OS_USERNAME': '******',
            'OS_PASSWORD': '',
            'OS_PROJECT_NAME': 'admin',
            'OS_AUTH_URL': 'http://127.0.0.1:5000/v3',
            'OS_USER_DOMAIN_NAME': 'Default',
            'OS_DOMAIN_ID': 'Default',
            'OS_PROJECT_DOMAIN_NAME': 'Default'}
        self.env_vars = {
            k[3:].lower(): os.getenv(k, v)
            for (k,v) in env_vars_default.items()
        }

        self.admin_client_manager = ClientManager(**self.env_vars)

        """
        Used a few places to get keystone objects by string
        """
        self.ks_attr = lambda t: getattr(
            self.admin_client_manager.get_keystone(), "%ss" % t)
Esempio n. 7
0
    def __init__(self):
        self.product_manager = ProductManager()
        self.warehouse_manager = WarehouseManager()
        self.order_manager = OrderManager()
        self.client_manager = ClientManager()
        self.product_group_manager = ProductGroupManager()
        self.owner = Owner(
            "Yo Corp.",
            Contacts("Tomar", 123456789, 987654321, "*****@*****.**"))

        prods_list = self.product_manager.get_all().keys()
        self.product_group_manager.from_dict([{
            "id": 0,
            "name": "ALL PRODUCTS",
            "products": prods_list
        }, {
            "id": 1,
            "name": "OLD PRODUCTS",
            "products": []
        }])

        self.load()
    def __init__(self):
        """
        This is what holds the decryption keys for the hashes.
        It's really important that this doesn't change during
        a run, or you'll get different outputs.

        :param key: The shared key used for 2 way encryption.
        :type key: 16 character length string.
        :param iv: The initialization vector for reversing a hash.
        :type iv: binary number in bytes
        """
        self.__crypto_info = {
            'key': "Sixteen byte key",
            'iv': None #This gets populated on first use.
        }

        """
        This is the big map of users. The key is a representation
        of its role assignment (domain, project, role). The value
        is a credentials object.
        """
        self.__users = {}
        """
        These credentials are so that we can create anything we
        need to in keystone. They must be admin level credentials.

        """
        env_vars_default = {
            'OS_USERNAME': '******',
            'OS_PASSWORD': '',
            'OS_PROJECT_NAME': 'admin',
            'OS_AUTH_URL': 'http://127.0.0.1:5000/v3',
            'OS_USER_DOMAIN_NAME': 'Default',
            'OS_PROJECT_DOMAIN_NAME': 'Default'}
        self.env_vars = {
            k[3:].lower(): os.getenv(k, v)
            for (k,v) in env_vars_default.items()
        }

        self.admin_client_manager = ClientManager(**self.env_vars)

        """
        Used a few places to get keystone objects by string
        """
        self.ks_attr = lambda t: getattr(
            self.admin_client_manager.get_keystone(), "%ss" % t)
Esempio n. 9
0
    def find_user_credentials(self,
                              domain='default',
                              project='default',
                              role='member'):
        """
        Finds a user that matches your auth needs, creating one if necessary.

        :param domain: Keystone domain. Defaults to project's value.
        :type domain: string
        :param project: Keystone project. Default to `Default`
        :type project: string
        :param role: Keystone role. If left empty, will default to member
        :type role: string
        :returns: clients.ClientManager
        """
        if domain == '' or domain == None:
            domain = project
        hash = self._encode_hash(domain, project, role)
        if hash in self.__users.keys():
            return self.__users[hash]
        else:
            domain_resource = self._ensure_keystone_resource("domain", domain)
            project_resource = self._ensure_keystone_resource(
                "project", project, domain)
            user_resource = self._ensure_keystone_resource(
                "user", "test-user-%s" % self.get_random_string(6), domain,
                project)
            role_resource = self._ensure_keystone_resource("role", role)
            role_requirement_resources = self.create_role_assignments(
                role_resource, user_resource, domain_resource,
                project_resource)
            """
            Finally build or fetch the user's client manager.
            """
            user_kwargs = {
                'username': user_resource.name,
                'password': user_resource.password,
                'project_name': project_resource.name,
                'auth_url': self.env_vars['auth_url'],
                'user_domain_name': domain_resource.name,
                'project_domain_name': domain_resource.name
            }
            self.__users[hash] = ClientManager(**user_kwargs)
            return self.__users[hash]
Esempio n. 10
0
def run():
    logger.info("Starting randomload...")
    actions = [
        server_create, server_delete, image_create, image_delete,
        volume_create, volume_delete
    ]
    args = argparser.parse_args()
    conf = config.load(args.config_file)
    interval = conf.get('interval', 60)

    clients = ClientManager(**conf.get('auth_kwargs', {}))

    last_action_time = 0
    while True:
        now = time.time()
        if now - last_action_time > interval:
            action = utils.randomfromlist(actions)
            try:
                action(clients, conf=conf)
            except Exception as e:
                print e
            last_action_time = time.time()
        time.sleep(1)
Esempio n. 11
0
class KeystoneManager(object):
    """
    Class for ensuring role assignments in keystone.

    Give it a role assignment, and it will return a user
    that matches your demands. That may include making
    any missing components (i.e., domain, project, user,
    role) and return back a fresh user.
    """
    def __init__(self):
        """
        This is what holds the decryption keys for the hashes.
        It's really important that this doesn't change during
        a run, or you'll get different outputs.

        :param key: The shared key used for 2 way encryption.
        :type key: 16 character length string.
        :param iv: The initialization vector for reversing a hash.
        :type iv: binary number in bytes
        """
        self.__crypto_info = {
            'key': "Sixteen byte key",
            'iv': None  #This gets populated on first use.
        }
        """
        This is the big map of users. The key is a representation
        of its role assignment (domain, project, role). The value
        is a credentials object.
        """
        self.__users = {}
        """
        These credentials are so that we can create anything we
        need to in keystone. They must be admin level credentials.

        """
        env_vars_default = {
            'OS_USERNAME': '******',
            'OS_PASSWORD': '',
            'OS_PROJECT_NAME': 'admin',
            'OS_AUTH_URL': 'http://127.0.0.1:5000/v3',
            'OS_USER_DOMAIN_NAME': 'Default',
            'OS_PROJECT_DOMAIN_NAME': 'Default'
        }
        self.env_vars = {
            k[3:].lower(): os.getenv(k, v)
            for (k, v) in env_vars_default.items()
        }

        self.admin_client_manager = ClientManager(**self.env_vars)
        """
        Used a few places to get keystone objects by string
        """
        self.ks_attr = lambda t: getattr(
            self.admin_client_manager.get_keystone(), "%ss" % t)

    def teardown(self):
        """
        Need to ensure all users created during this are destroyed.
        """
        for u in self.__users.values():
            ks = self.admin_client_manager.get_keystone()
            username = u.auth_kwargs['username']
            usr_test = [x for x in ks.users.list() if x.name == username]
            if usr_test != []:
                usr = usr_test[0]
                ks.users.delete(usr)

    def get_random_string(self, length):
        """
        Generates really nice random strings
        :param length: random string length
        :type length: int
        :returns: string
        """
        return ''.join(
            [random.choice(ascii_letters + digits) for x in range(length)])

    def _get_cypher(self):
        """
        Builds a cypher for encryption/decryption

        :returns: (Crypto.Cipher.AES, bytes)
        """
        key = self.__crypto_info['key']
        iv = None
        if self.__crypto_info['iv'] == None:
            iv = Random.new().read(AES.block_size)
            self.__crypto_info['iv'] = iv
        else:
            iv = self.__crypto_info['iv']
        return (AES.new(key, AES.MODE_CFB, iv), iv)

    def find_user_credentials(self,
                              domain='default',
                              project='default',
                              role='member'):
        """
        Finds a user that matches your auth needs, creating one if necessary.

        :param domain: Keystone domain. Defaults to project's value.
        :type domain: string
        :param project: Keystone project. Default to `Default`
        :type project: string
        :param role: Keystone role. If left empty, will default to member
        :type role: string
        :returns: clients.ClientManager
        """
        if domain == '' or domain == None:
            domain = project
        hash = self._encode_hash(domain, project, role)
        if hash in self.__users.keys():
            return self.__users[hash]
        else:
            domain_resource = self._ensure_keystone_resource("domain", domain)
            project_resource = self._ensure_keystone_resource(
                "project", project, domain)
            user_resource = self._ensure_keystone_resource(
                "user", "test-user-%s" % self.get_random_string(6), domain,
                project)
            role_resource = self._ensure_keystone_resource("role", role)
            role_requirement_resources = self.create_role_assignments(
                role_resource, user_resource, domain_resource,
                project_resource)
            """
            Finally build or fetch the user's client manager.
            """
            user_kwargs = {
                'username': user_resource.name,
                'password': user_resource.password,
                'project_name': project_resource.name,
                'auth_url': self.env_vars['auth_url'],
                'user_domain_name': domain_resource.name,
                'project_domain_name': domain_resource.name
            }
            self.__users[hash] = ClientManager(**user_kwargs)
            return self.__users[hash]

    def create_role_assignments(self,
                                role=None,
                                user=None,
                                domain=None,
                                project=None):
        """
        Make role assignments from a list of keystone resources

        :param role: The role to be assigned. This is required.
        :type role: keystoneclient.v3.roles.Role
        :param user: The user to be bound to the role. This is required.
        :type user: keystoneclient.v3.users.User
        :param domain: The domain object. *args must match domain ^ project
        :type domain: keystoneclient.v3.domains.Domain
        :param project: The project object. *args must match domain ^ project
        :type project: keystoneclient.v3.projects.Project
        :returns: [keystoneclient.v3.role_assignments.RoleAssignment]
        """
        ks = self.admin_client_manager.get_keystone()
        """
        Because a role must have domain ^ project, we have to make as many
        roles as necessary to please the client. Thus data is coppied
        so it doesn't pollute the next run.

        It's worth noting the specific args ordering we are building is:
        role, user, group, domain, project
        """
        role_assignment = [role, user, None]  #build-a-request
        role_possibilities = [domain, project]  #unknown state
        role_assignments = []  # Final list of required assignments
        if None in role_possibilities:
            # if [0,0], [0,1], or [1,0]
            role_assignments = [role_assignment + role_possibilities]
        else:
            # [1,1]
            role_assignments = [
                role_assignment + [role_possibilities[0]] + [None],
                role_assignment + [None] + [role_possibilities[1]]
            ]
            return [ks.roles.grant(*x) for x in role_assignments]

    def get_resource_by_name(self, name, resource_type):
        """
        Fetches a keystone resource by name.

        Assumes names are unique, or at very least will just
        return the first matching entity.
        :param name: name of the object to find
        :type name: string
        :param resource_type: name of object type
        :type resource_type: string
        :returns: keystoneclient.base.Resource
        """
        if name == None:  # None specified by user
            return None
        ks = self.admin_client_manager.get_keystone()
        collection = [
            x for x in self.ks_attr(resource_type).list() if x.name == name
        ]
        if collection == []:
            return None
        else:
            return collection[0]

    def _encode_hash(self, *args):
        """
        Hashes a list of *args into a single value.

        :param: list of strigs to pack
        :type *args: [string]
        :returns: string
        """
        text = '|'.join(args)
        (cipher, iv) = self._get_cypher()
        msg = iv + cipher.encrypt(text)
        return msg.encode('hex')

    def _decode_hash(self, hash):
        """
        Decodes a hashed string created by _encode_hash().

        Not really used, but handy to have in case something goes sideways.

        :param hash: A hashed list
        :type hash: string
        :returns: string
        """
        (cipher, iv) = self._get_cypher()
        return cipher.decrypt(hash.decode('hex'))[len(iv):].split('|')

    def _entity_exists(self, keystone_type, name):
        """
        Checks to see if keystone has a matching record.

        :param keystone_type: Keystone resource "project" || "domain" || "role"
        :type keystone_type: string
        :param name: matching name, like `member` for a role
        :type name: string
        :returns: boolean
        """
        ks = self.admin_client_manager.get_keystone()
        return name in [x.name for x in getattr(ks, keystone_type).list()]

    def _ensure_keystone_resource(self,
                                  keystone_resource_type,
                                  name,
                                  domain_name=None,
                                  project_name=None):
        """
        Gets (or creates and returns) a keystone domain by name.

        :param name: Keystone domain name
        :type name: string
        :returns: keystoneclient.v3.domains.Domain
        """

        ks = self.admin_client_manager.get_keystone()  # used like, everywhere

        # clarity
        resources = self.ks_attr(keystone_resource_type)
        """
        check whether a keystone object exists in its list by name.
        :returns: boolean
        """
        entity_exists = lambda name: name in [x.name for x in resources.list()]
        """
        these become the *args that are sent to create() methods in keystone.
        """
        all_args = {
            "role": [name],
            "domain": [name],
            "project":
            [name, self.get_resource_by_name(domain_name, 'domain')],
            "user": [
                name,
                self.get_resource_by_name(domain_name, 'domain'),
                self.get_resource_by_name(project_name, 'project')
            ]
        }

        if entity_exists(name) == False:
            """
            create the resource!
            """
            my_args = all_args[keystone_resource_type]
            if keystone_resource_type == 'user':
                """
                User has an extra field (password) that needs to be tagged on.
                Conveniently, it is stored last in *args position
                """
                password = self.get_random_string(32)
                my_args.append(password)
                # Hijack the user, add password so we can slurp it on return
                user = resources.create(*my_args)
                user.password = password
                return user
            else:
                """
                non-user objects are all standard
                """
                return resources.create(*my_args)
        else:
            """
            load the resource
            """
            return [
                resources.get(x.id) for x in resources.list() if x.name == name
            ][0]
Esempio n. 12
0
class Inventory(Interface):
    def __init__(self):
        self.product_manager = ProductManager()
        self.warehouse_manager = WarehouseManager()
        self.order_manager = OrderManager()
        self.client_manager = ClientManager()
        self.product_group_manager = ProductGroupManager()
        self.owner = Owner(
            "Yo Corp.",
            Contacts("Tomar", 123456789, 987654321, "*****@*****.**"))

        prods_list = self.product_manager.get_all().keys()
        self.product_group_manager.from_dict([{
            "id": 0,
            "name": "ALL PRODUCTS",
            "products": prods_list
        }, {
            "id": 1,
            "name": "OLD PRODUCTS",
            "products": []
        }])

        self.load()

    def save(self, command=False):
        if command:
            return "Save"

        final_dict = dict()
        final_dict["owner"] = self.owner.to_dict()
        final_dict["products"] = self.product_manager.to_dict()["products"]
        final_dict["warehouses"] = self.warehouse_manager.to_dict(
        )["warehouses"]
        final_dict["orders"] = self.order_manager.to_dict()["orders"]
        final_dict["clients"] = self.client_manager.to_dict()["clients"]
        final_dict["product_groups"] = self.product_group_manager.to_dict(
        )["product_groups"]

        with open("data.json", "w") as file:
            json.dump(final_dict, file)

    def load(self, command=False):
        if command:
            return "Load"

        with open("data.json", "r") as file:
            data = json.load(file)

        contact_data = data["owner"]["contacts"]
        contacts = Contacts(contact_data["adress"], contact_data["mobile"],
                            contact_data["nif"], contact_data["email"])
        self.owner = Owner(data["owner"]["name"], contacts)
        self.product_manager.from_dict(data["products"])
        self.warehouse_manager.from_dict(data["warehouses"])
        self.order_manager.from_dict(data["orders"])
        self.client_manager.from_dict(data["clients"])
        self.product_group_manager.from_dict(data["product_groups"])

    def get_order_by_client(self, command=False):
        if command:
            return "Order By Client"

        self.list_clients()
        client = 0
        while client not in self.client_manager.get_all().keys():
            client = int(input("Which Client? "))

        for ident, order in self.order_manager.get_by_client(client).items():
            products = {
                ref: product.get_amount()
                for ref, product in order.get_products().items()
            }
            print("\t" + str(ident) + " -> " + str(products) + " - " +
                  str(order.total_price()) + "$")

    def search_client(self, command=False):
        if command:
            return "Search Client"

        for client in self.client_manager.search_by_query(input("Query: ")):
            print("\t" + client.get_name() + "\t\t" + str(client.get_nif()) +
                  "\t" + str(client.get_mobile()))

    def discontinue_product(self, command=False):
        if command:
            return "Discontinue"

        self.list_products()
        product = ""
        while product not in self.product_manager.get_all().keys():
            product = input("Which Product? ")

        if self.product_group_manager.get_by_id(0).is_in_group(product):
            self.product_group_manager.get_by_id(0).remove_product(product)
            self.product_group_manager.get_by_id(1).add_product(product)
        else:
            print("Product is already discontinued")

    def make_current(self, command=False):
        if command:
            return "Make Current"

        self.list_products()
        product = ""
        while product not in self.product_manager.get_all().keys():
            product = input("Which Product? ")

        if self.product_group_manager.get_by_id(1).is_in_group(product):
            self.product_group_manager.get_by_id(1).remove_product(product)
            self.product_group_manager.get_by_id(0).add_product(product)
        else:
            print("Product is already current")

    def create_client(self, command=False):
        if command:
            return "Create Client"

        self.client_manager.new_client(input("Client Name: "),
                                       int(input("Client NIF: ")),
                                       int(input("Client Mobile: ")))

    def create_product_group(self, command=False):
        if command:
            return "Create Product Group"

        self.product_group_manager.new_group(input("Group Name: "))

    def add_to_group(self, command=False):
        if command:
            return "Add To Group"

        self.list_groups()
        group = ""
        while group not in self.product_group_manager.get_groups().keys():
            group = int(input("To Which Group? "))

        self.list_products()
        product = ""
        while product not in self.product_manager.get_all().keys():
            product = input("Which Product? ")

        self.product_group_manager.get_by_id(group).add_product(product)

    def list_groups(self, command=False):
        if command:
            return "List Groups"

        for ident, group in self.product_group_manager.get_groups().items():
            print("\t" + str(ident) + " -> " + group.name + " - " +
                  ", ".join(group.get_products()))

    def list_clients(self, command=False):
        if command:
            return "List Clients"

        for ident, client in self.client_manager.get_all().items():
            print("\t" + str(ident) + " -> " + client.get_name() + " :\t" +
                  str(client.get_contacts().get_nif()) + "\t" +
                  str(client.get_contacts().get_mobile()))

    def list_orders(self, command=False):
        if command:
            return "List Orders"

        for ident, order in self.order_manager.get_all().items():
            print("\t" + str(ident) + " -> " + str(order.get_client()) + ": " +
                  str(order.total_price()))

    def open_order(self, command=False):
        if command:
            return "Open Order"

        self.list_orders()

        order = 0
        while order not in self.order_manager.get_all().keys():
            order = int(input("Which One? "))

        order = CreateOrder(self.product_manager.get_all(),
                            self.client_manager.get_all(), self.owner,
                            self.order_manager.get_by_id(order))
        order.run()

    def create_order(self, command=False):
        if command:
            return "Create Order"

        self.list_products()
        print("Select the products and then enter 'quit' when you've finished")

        order = CreateOrder(self.product_manager.get_all(),
                            self.client_manager.get_all(), self.owner)
        order.run()
        self.order_manager.add_order(order.order)

    def create_warehouse(self, command=False):
        if command:
            return "Create Warehouse"

        self.warehouse_manager.new_warehouse(input("Warehouse Name: "))

    def list_warehouses(self, command=False):
        if command:
            return "List Warehouses"

        for ident, warehouse in self.warehouse_manager.get_all().items():
            print("\t" + str(ident) + " -> " + warehouse.name)

    def add_stock_to_warehouse(self, command=False):
        if command:
            return "Add To Stock"

        self.list_warehouses()

        warehouse_selected = -1
        while warehouse_selected < 0 or warehouse_selected > self.warehouse_manager.get_warehouses_num(
        ) - 1:
            warehouse_selected = int(input("Which Warehouse To? "))

        product_reference = ""
        while product_reference not in self.product_manager.get_all():
            product_reference = input("Product Reference: ")

        amount = 0
        while amount <= 0:
            amount = int(input("Amount: "))

        self.warehouse_manager.get_by_id(warehouse_selected).add_to_stock(
            product_reference, amount)

    def take_stock_from_warehouse(self, command=False):
        if command:
            return "Take From Stock"

        self.list_warehouses()

        warehouse_selected = -1
        while warehouse_selected < 0 or warehouse_selected > self.warehouse_manager.get_warehouses_num(
        ) - 1:
            warehouse_selected = int(input("Which Warehouse To? "))

        product_reference = ""
        while product_reference not in self.product_manager.get_all():
            product_reference = input("Product Reference: ")

        amount = 0
        while amount <= 0:
            amount = int(input("Amount: "))

        self.warehouse_manager.get_by_id(warehouse_selected).take_from_stock(
            product_reference, amount)

    def check_product_stock(self, command=False):
        if command:
            return "Check Product Stock"

        product_reference = ""
        while product_reference not in self.product_manager.get_all():
            product_reference = input("Product Reference: ")

        for warehouse in self.warehouse_manager.get_all().values():
            print("\t" + warehouse.name + " -> " +
                  str(warehouse.get_stock_by_reference(product_reference)))

    def create_product(self, command=False):
        if command:
            return "Create Product"

        name = input("Product Name:")
        price = float(input("Product Price:"))
        iva = int(input("Product IVA:"))
        reference = input("Product Reference:")

        if self.product_manager.new_product(name,
                                            float("{0:.2f}".format(price)),
                                            reference, iva):
            self.product_group_manager.get_by_id(0).add_product(reference)
            print("Product created successfully!")
        else:
            print("Error while creating the product...")

    def list_products(self, command=False):
        if command:
            return "List Products"

        self.list_groups()
        group = ""
        while group not in self.product_group_manager.get_groups().keys():
            group = int(input("Which Group? "))

        group = self.product_group_manager.get_by_id(group)

        for ref in group.get_products():
            product = self.product_manager.get_by_reference(ref)
            print("\t" + ref + " -> " + product.get_name() + " :\t" +
                  str(product.get_price()) + "$ (" + str(product.get_iva()) +
                  "% IVA)")

    def get_product_by_reference(self, command=False):
        if command:
            return "Get Reference"

        reference = input("Reference: ")
        product = self.product_manager.get_by_reference(reference)

        if product:
            print("\t" + reference + " -> " + product.get_name() + " :\t" +
                  str(product.get_price()) + "$")
        else:
            print("No such reference")

    def search_product(self, command=False):
        if command:
            return "Search Product"

        for ref, product in self.product_manager.search_by_query(
                input("Query: ")).items():
            print("\t" + ref + " -> " + product.get_name() + " :\t" +
                  str(product.get_price()) + "$")

    def behaviour(self):
        return [
            self.create_product, self.list_products,
            self.get_product_by_reference, self.search_product,
            self.create_warehouse, self.list_warehouses,
            self.add_stock_to_warehouse, self.take_stock_from_warehouse,
            self.check_product_stock, self.create_order, self.create_client,
            self.create_product_group, self.add_to_group, self.list_groups,
            self.list_clients, self.discontinue_product, self.make_current,
            self.search_client, self.get_order_by_client, self.list_orders,
            self.open_order, self.save, self.load
        ]

    def run(self):
        super().run(self.behaviour())
Esempio n. 13
0
class KeystoneManager(object):
    """
    Class for ensuring role assignments in keystone.

    Give it a role assignment, and it will return a user
    that matches your demands. That may include making
    any missing components (i.e., domain, project, user,
    role) and return back a fresh user.
    """

    def __init__(self):
        """
        This is what holds the decryption keys for the hashes.
        It's really important that this doesn't change during
        a run, or you'll get different outputs.

        :param key: The shared key used for 2 way encryption.
        :type key: 16 character length string.
        :param iv: The initialization vector for reversing a hash.
        :type iv: binary number in bytes
        """
        self.__crypto_info = {
            'key': "Sixteen byte key",
            'iv': None #This gets populated on first use.
        }

        """
        This is the big map of users. The key is a representation
        of its role assignment (domain, project, role). The value
        is a credentials object.
        """
        self.__users = {}
        """
        These credentials are so that we can create anything we
        need to in keystone. They must be admin level credentials.

        """
        env_vars_default = {
            'OS_USERNAME': '******',
            'OS_PASSWORD': '',
            'OS_PROJECT_NAME': 'admin',
            'OS_AUTH_URL': 'http://127.0.0.1:5000/v3',
            'OS_USER_DOMAIN_NAME': 'Default',
            'OS_PROJECT_DOMAIN_NAME': 'Default'}
        self.env_vars = {
            k[3:].lower(): os.getenv(k, v)
            for (k,v) in env_vars_default.items()
        }

        self.admin_client_manager = ClientManager(**self.env_vars)

        """
        Used a few places to get keystone objects by string
        """
        self.ks_attr = lambda t: getattr(
            self.admin_client_manager.get_keystone(), "%ss" % t)

    def teardown(self):
        """
        Need to ensure all users created during this are destroyed.
        """
        for u in self.__users.values():
            ks = self.admin_client_manager.get_keystone()
            username = u.auth_kwargs['username']
            usr_test = [x for x in ks.users.list() if x.name==username]
            if usr_test != []:
                usr = usr_test[0]
                ks.users.delete(usr)

    def get_random_string(self, length):
        """
        Generates really nice random strings
        :param length: random string length
        :type length: int
        :returns: string
        """
        return ''.join(
            [random.choice(ascii_letters + digits)
            for x in range(length)])

    def _get_cypher(self):
        """
        Builds a cypher for encryption/decryption

        :returns: (Crypto.Cipher.AES, bytes)
        """
        key = self.__crypto_info['key']
        iv = None
        if self.__crypto_info['iv'] == None:
            iv = Random.new().read(AES.block_size)
            self.__crypto_info['iv'] = iv
        else:
            iv = self.__crypto_info['iv']
        return (AES.new(key, AES.MODE_CFB, iv), iv)

    def find_user_credentials(self,
        domain='default',
        project='default',
        role='member'):
        """
        Finds a user that matches your auth needs, creating one if necessary.

        :param domain: Keystone domain. Defaults to project's value.
        :type domain: string
        :param project: Keystone project. Default to `Default`
        :type project: string
        :param role: Keystone role. If left empty, will default to member
        :type role: string
        :returns: clients.ClientManager
        """
        if domain == '' or domain == None:
            domain = project
        hash = self._encode_hash(domain, project, role)
        if hash in self.__users.keys():
            return self.__users[hash]
        else:
            domain_resource = self._ensure_keystone_resource(
                "domain",
                domain)
            project_resource = self._ensure_keystone_resource(
                "project",
                project,
                domain)
            user_resource = self._ensure_keystone_resource(
                "user",
                "test-user-%s" % self.get_random_string(6),
                domain,
                project)
            role_resource = self._ensure_keystone_resource(
                "role",
                role)
            role_requirement_resources = self.create_role_assignments(
                role_resource,
                user_resource,
                domain_resource,
                project_resource
            )
            """
            Finally build or fetch the user's client manager.
            """
            user_kwargs = {
                'username': user_resource.name,
                'password': user_resource.password,
                'project_name': project_resource.name,
                'auth_url': self.env_vars['auth_url'],
                'user_domain_name': domain_resource.name,
                'project_domain_name': domain_resource.name
            }
            self.__users[hash] = ClientManager(**user_kwargs)
            return self.__users[hash]

    def create_role_assignments(self,
        role=None,
        user=None,
        domain=None,
        project=None):
        """
        Make role assignments from a list of keystone resources

        :param role: The role to be assigned. This is required.
        :type role: keystoneclient.v3.roles.Role
        :param user: The user to be bound to the role. This is required.
        :type user: keystoneclient.v3.users.User
        :param domain: The domain object. *args must match domain ^ project
        :type domain: keystoneclient.v3.domains.Domain
        :param project: The project object. *args must match domain ^ project
        :type project: keystoneclient.v3.projects.Project
        :returns: [keystoneclient.v3.role_assignments.RoleAssignment]
        """
        ks = self.admin_client_manager.get_keystone()
        """
        Because a role must have domain ^ project, we have to make as many
        roles as necessary to please the client. Thus data is coppied
        so it doesn't pollute the next run.

        It's worth noting the specific args ordering we are building is:
        role, user, group, domain, project
        """
        role_assignment = [role, user, None] #build-a-request
        role_possibilities = [domain, project] #unknown state
        role_assignments = [] # Final list of required assignments
        if None in role_possibilities:
            # if [0,0], [0,1], or [1,0]
            role_assignments = [role_assignment + role_possibilities]
        else:
            # [1,1]
            role_assignments = [
                role_assignment
                + [role_possibilities[0]]
                + [None],
                role_assignment
                + [None]
                + [role_possibilities[1]]
            ]
            return [ks.roles.grant(*x) for x in role_assignments]

    def get_resource_by_name(self, name, resource_type):
        """
        Fetches a keystone resource by name.

        Assumes names are unique, or at very least will just
        return the first matching entity.
        :param name: name of the object to find
        :type name: string
        :param resource_type: name of object type
        :type resource_type: string
        :returns: keystoneclient.base.Resource
        """
        if name == None: # None specified by user
            return None
        ks = self.admin_client_manager.get_keystone()
        collection = [x
            for x in self.ks_attr(resource_type).list()
            if x.name == name]
        if collection == []:
            return None
        else:
            return collection[0]


    def _encode_hash(self, *args):
        """
        Hashes a list of *args into a single value.

        :param: list of strigs to pack
        :type *args: [string]
        :returns: string
        """
        sanitized_args = ["%s" % x for x in args]
        text = '|'.join(sanitized_args)
        (cipher, iv) = self._get_cypher()
        msg = iv + cipher.encrypt(text)
        return msg.encode('hex')


    def _decode_hash(self, hash):
        """
        Decodes a hashed string created by _encode_hash().

        Not really used, but handy to have in case something goes sideways.

        :param hash: A hashed list
        :type hash: string
        :returns: string
        """
        (cipher, iv) = self._get_cypher()
        return cipher.decrypt(hash.decode('hex'))[len(iv):].split('|')

    def _entity_exists(self, keystone_type, name):
        """
        Checks to see if keystone has a matching record.

        :param keystone_type: Keystone resource "project" || "domain" || "role"
        :type keystone_type: string
        :param name: matching name, like `member` for a role
        :type name: string
        :returns: boolean
        """
        ks = self.admin_client_manager.get_keystone()
        return name in [x.name for x in getattr(ks, keystone_type).list()]

    def _ensure_keystone_resource(self,
        keystone_resource_type,
        name,
        domain_name=None,
        project_name=None):
        """
        Gets (or creates and returns) a keystone domain by name.

        :param name: Keystone domain name
        :type name: string
        :returns: keystoneclient.v3.domains.Domain
        """

        ks = self.admin_client_manager.get_keystone() # used like, everywhere

        # clarity
        resources = self.ks_attr(keystone_resource_type)

        """
        check whether a keystone object exists in its list by name.
        :returns: boolean
        """
        entity_exists = lambda name: name in [x.name for x in resources.list()]

        """
        these become the *args that are sent to create() methods in keystone.
        """
        all_args = {
            "role": [name],
            "domain": [name],
            "project": [
                name,
                self.get_resource_by_name(domain_name, 'domain')],
            "user": [
                name,
                self.get_resource_by_name(domain_name, 'domain'),
                self.get_resource_by_name(project_name, 'project')
            ]

        }

        if entity_exists(name) == False:
            """
            create the resource!
            """
            my_args = all_args[keystone_resource_type]
            if keystone_resource_type == 'user':
                """
                User has an extra field (password) that needs to be tagged on.
                Conveniently, it is stored last in *args position
                """
                password = self.get_random_string(32)
                my_args.append(password)
                # Hijack the user, add password so we can slurp it on return
                user = resources.create(*my_args)
                user.password = password
                return user
            else:
                """
                non-user objects are all standard
                """
                return resources.create(*my_args)
        else:
            """
            load the resource
            """
            return [resources.get(x.id)
                for x in resources.list()
                if x.name == name][0]