HTTPS SSH

Known Issues

None: If any issues are discovered please let me know at my email listed below.

What is this repository for?

The Plexxi Driver is code written to integrate PlexxiCore with the Openstack Policy engine Congress. It allows congress to create and populate tables with data gained from PlexxiCore for use in future Polices.
Within this driver, there is an built in Policy that can be enabled in configuration that will check the tables created by a driver that connects with Nova, the Open stack Compute service, to ensure that no two Virtual Machines in the different sets of data are named same. If any duplicate names are found, it will automatically be corrected by the Driver by changing the name in the PlexxiCore Database. An example demonstration of this can be seen here (no audio) or here (audio).

As of November 21st, a version of this driver now comes with congress as part of the congress download.

How do I get set up?

You will first need congress installed to use the PlexxiDriver. If you do not have Congress, you can find it with installation instructions at https://github.com/stackforge/congress

If you are just installing congress you will need to edit the config file that the congress server uses. In a standard devstack install this will be:

/etc/congress/congress.conf

Here change the 'auth_strategry' to 'noauth' and any other options you may wish to configure for your congress server

You will also need to have the PlexxiCore python files for your respective PlexxiCore version installed on the machine running congress as the driver uses classes from this package. To check what version of PlexxiCore is running, go to http://PlexxiCoreURL:8080/PlexxiCore/. Then run the following command with your core version in place of '2.0.2-sp2':

pip install -v --index-url http://pypi.plexxi.com plexxi==2.0.2-sp2

This command can be found and executed from the setup_plexxi.sh file instead of being run manually.

2.0.2sp1 note: Installing the Plexxi package may downgrade some other congress dependencies below the required level, such as 'requests', and 'pytz'. In this case, upgrade the packages causing issues with pip.

sudo pip install --upgrade pytz

Then you must modify your datasources.conf that your congress server is using to use the Plexxi Driver. In a standard devstack install this will be

/etc/congress/datasources.conf

Newer versions of congress have removed datasources.conf in favor of allowing datasources to be configured while congress is running through the API The change is documented in this commit.

Add:

[plexxi]
module:datasources/plexxi_driver.py
username: plexxiCore_username
password: plexxiCore_password
tenant_name: openstackuser
auth_url: http://PlexxiCoreURL/PlexxiCore/api
unique_names: False

(If using Keystone)
keystone_pass:  keystonepassword
keystone_user': keystoneusername

'unique_names=False' disables the name detection policy shown in this demo. If your congress server has already been configured to disable keystone this will now enable the PlexxiDriver the next time the congress server is restarted.

An example datatsources.conf is included.

You can restart the congress server on a standard Devstack install with

screen -x stack
//navigate to the congress screen
ctrl+c
//wait for server to stop
[up arrow] to most recent command
enter

Contribution guidelines

Currently two directions contributions can go towards is expanding the variety of data being pulled form PlexxiCore or adding new policy features.

The way the PlexxiDriver formats its data attempts to stick as close to a relational data model as possible.

Expanding Data Input

To expand the amount of data being pulled from PlexxiCore with the current code configuration, First decide on what data you would like to pull and establish a directory in the get_schema() function, then create the function for translating the data from congress and finally implement your new function in Update_From_data_source()

get_schema()

1: To add a new entry in the method for your data, first define a class wide variable at the top of the class with the name of your new data type

  class PlexxiDriver(DataSourceDriver):
    HOSTS = "hosts"

2: Inside get_schema() , add a new key in the dictionary for your new Data object, containing the list of data that will be provided about this new object in the order that the data will be displayed

d[cls.HOSTS] = ("uuid", "name", "mac_count", "vmcount")

_translate_newdata():

1: This function should take self and the data set that it will be translating as parameters

2: Get your row_keys by using the base class method get_column_map() and add this key to the key index

3: Create empty lists that will serve as your tables

4: Parse through your data and create 'rows'. You should use

row = ['None'] * (max(row_keys.values()) + 1)
to create your row list.

5: Extract your data objects and place each element from the object in the position you have defined with your row keys

6: Place your row in the list you created in step 3 and create a global variable containing this data

Example:

    def _translate_pswitches(self, plexxi_switches):
        """
        Translates data on Plexxi Switches from PlexxiCore for Congress
        Responsible for state 'Plexxi_swtiches' and 'Plexxi_switches.macs'
        """
        row_keys = self.get_column_map(self.PLEXXISWITCHES)
        if self.PLEXXISWITCHES not in self.key_check:
            self.key_index.append(row_keys)
            self.key_check.append(self.PLEXXISWITCHES)
        pslist = []
        maclist = []
        for switch in plexxi_switches:
            row = ['None'] * (max(row_keys.values()) + 1)
            psuuid = str(switch.getUuid())
            row[row_keys['pswitch_uuid']] = psuuid
            psip = str(switch.getIpAddress())
            row[row_keys['pswitch_ip']] = psip
            psstatus = str(switch.getStatus())
            row[row_keys['pswitch_status']] = psstatus
            pnics = switch.getPhysicalNetworkInterfaces()
            for pnic in pnics:
                mac = str(pnic.getMacAddress())
                macrow = [psuuid, mac]
                maclist.append(tuple(macrow))
            pslist.append(tuple(row))
        self.plexxi_switches = pslist
        self.plexxi_switches_macs = maclist

This example also shows creating a secondary list for mac addresses as we want to avoid creating multiple a row element that contains a list, so we create another table joined to the main table by its Uuid

update_from_datasource()

This function is the method called by the congress DSE, so it essentially functions like a main() as far congress is concerned.

1: Initialize your new data list at the top of the method.

2: Obtain all of the objects of your type from PlexxiCore

3: Check that the data in Congress is not identical to the new data coming in or if the data is not yet in Congress

4: If the data needs to be replaced, call your translation method and set a new raw_state so that Congress knows what the incoming data looks like. Else, re-declare your states to the same as they where from the last time your translate method was ran

5: Set your state

Example:

self.hosts = []
#....
        # Get host data from PlexxiCore
        hosts = VirtualizationHost.getAll(session=self.exchange)
        if (self.HOSTS not in self.state or
           hosts != self.raw_state[self.HOSTS]):
            self._translate_hosts(hosts)
            self.raw_state[self.HOSTS] = hosts
        else:
            self.hosts = self.state[self.HOSTS]
            self.mac_list = self.state['hosts.macs']
            self.guest_list = self.state['hosts.guests']
#....
        self.state[self.HOSTS] = set(self.hosts)
        self.state['hosts.macs'] = set(self.mac_list)
        self.state['hosts.guests'] = set(self.guest_list)

Writing new Policies

A very brief overview of how to add new Policies. Depending on exactly what you are trying to add the details will vary, but these three steps should be applicable to most cases.

1: First Create an option to enable and disable your policy in driver config in the init method

        self.unique_names = self.string_to_bool(args['unique_names'])

2: Create corresponding methods for your policy. This will involve creating tables using the datalog language. Once your tables are created it is then possible extracting data from these tables as they are populated and then acting of the results of this data.

3: Call your new methods at the end of update_from_datasource() after checking if the policy was enabled in the configuration file.

Testing

The files included in the test folder are designed to be used on the machine that congress is running on. To execute tests, place the two files found in the Tests Folder in

path/to/congress/congress//tests/datasources

When the testing files are in place as well as the main driver you can the command below to test the driver

python -m unittest test_plexxi_driver.TestPlexxiDriver

The output should look similar to

......
----------------------------------------------------------------------
Ran 6 tests in 0.047s

OK

Who do I talk to?

If you encounter any issues,suggestions, or questions you can contact me at conner.ferguson1@marist.edu