コード例 #1
0
def get_connection_status():
    """Return the eth & wlan connection status of the specified probe,

    The only argument is mac, which should be the probe's MAC address
    Returned statuses will be either:
        invalid-mac
        unknown-mac
        {"eth0": 0 or 1, "wlan0": 1 or 0}

        For backwards compatibility:
        connected
    """
    mac = request.args.get('mac', '')
    if mac == '':
        return 'invalid-mac'

    mac = util.convert_mac(mac, 'storage')
    probe = database.get_probe(mac)
    if probe is None:
        return 'unknown-mac'

    status = util.is_probe_connected(probe.port)
    if status:
        con_stat = util.get_interface_connection_status(probe.port)
        if con_stat is not None:
            return con_stat
        else:
            return 'connected'

    return '{"eth0": 0, "wlan0": 0}'
コード例 #2
0
def get_port():
    """Returns the port number associated with the supplied MAC.

    The port will be used to construct a SSH tunnel

    The function can give the following responses (with explanation):
        invalid-mac       : The supplied MAC was invalid (in format)
        unknown-mac       : The MAC was valid, but is not in the database
        no-registered-key : No SSH key has been associated with this MAC,
                            and therefore no port will be sent
        <port>            : Returns the queried port (a valid MAC was received)
    """
    mac = request.args.get('mac', '')
    if not util.is_mac_valid(mac):
        return 'invalid-mac'

    mac = util.convert_mac(mac, mode='storage')
    probe = database.get_probe(mac)

    if probe is None:
        return 'unknown-mac'

    if probe.pub_key == '' or probe.host_key == '':
        return 'no-registered-key'

    return str(probe.port)
コード例 #3
0
    def update_probe(self, current_probe_id, name=None, new_custom_id=None, location=None):
        """Update 'current_probe_id' with new attributes"""
        probe = self.get_probe(current_probe_id)
        if probe is None:
            return False

        conv_curr = util.convert_mac(current_probe_id, mode='storage')
        conv_new = util.convert_mac(new_custom_id, mode='storage')
        if not conv_curr == conv_new:
            if self.is_valid_id(new_custom_id):
                probe.custom_id = util.convert_mac(new_custom_id, mode='storage')
            else:
                return False

        if self.is_valid_string(name):
            probe.name = name
        if self.is_valid_string(location):
            probe.location = location

        return True
コード例 #4
0
    def is_valid_id(self, probe_id):
        """Return true if 'probe_id' is a valid MAC address for use as a
        probe id."""
        if not self.is_valid_string(probe_id):
            return False
        if not util.is_mac_valid(probe_id):
            return False

        probe_id = util.convert_mac(probe_id, mode='storage')
        is_unused = len(self.session.query(Probe.custom_id).filter(Probe.custom_id == probe_id).all()) == 0

        return is_unused
コード例 #5
0
def probe_setup():
    """Render page for adding/editing probe data. Also parse data
    on POST.

    More specifically, the data that can be changed are:
        - Basic probe info (name, MAC and location)
        - Script configurations (interval and enabled/disabled for each script)
        - Network configration (SSID, anon id, username, password, cert)
    """
    probe_id = request.args.get('id', '')
    if probe_id == '':
        flash('No probe ID specified')
        abort(404)

    probe_id = util.convert_mac(probe_id, mode='storage')
    probe = database.get_probe(probe_id)

    if probe is None or probe.user.username != current_user.username:
        flash('Unknown probe ID')
        abort(404)

    if request.method == 'POST':
        successful_script_update = form_parsers.update_scripts()
        successful_network_update = form_parsers.update_network_configs()
        successful_certificate_upload = form_parsers.upload_certificate(
            probe_id, current_user.username)
        successful_probe_update = form_parsers.update_probe(probe_id)

        if (successful_script_update and successful_probe_update
                and successful_network_update
                and successful_certificate_upload):
            database.save_changes()

            action = request.form.get('action', '')
            if action == 'save_as_default':
                ansible.export_group_config(
                    current_user.username,
                    {'group_script_configs': database.get_script_data(probe)},
                    'script_configs')
                ansible.export_group_config(
                    current_user.username,
                    {'networks': database.get_network_config_data(probe)},
                    'network_configs')

                ansible.make_certificate_default(probe_id,
                                                 current_user.username)

            return redirect(url_for('probes'))
        else:
            database.revert_changes()

    return generate_probe_setup_template(probe_id, current_user.username)
コード例 #6
0
 def valid_network_configs(self, probe, with_warning=False):
     """Returns true if 'probe's network config(s) has been filled out"""
     success = True
     for net_conf in probe.network_configs:
         # For now we just check for any (not two_g & and five_g), because
         # we don't use the two_g and five_g at the moment
         if net_conf.name == 'any' and not net_conf.is_filled():
             if with_warning:
                 message = messages.ERROR_MESSAGE['fill_out_network_credentials'].format(
                     str(probe.name) + ' / ' + util.convert_mac(probe.custom_id, mode='display'))
                 flash(message, 'error')
             success = False
     return success
コード例 #7
0
    def remove_probe(self, username, probe_custom_id):
        """Remove the probe with id 'probe_custom_id', as long as it belongs
        to 'username'"""
        probe = self.get_probe(probe_custom_id)
        if probe is None or self.get_user(username).id != probe.user_id:
            flash('Invalid probe ID', 'error')
            return False

        probe_id = util.convert_mac(probe_custom_id, mode='storage')
        ansible.remove_host_cert(probe_id)
        if probe is not None:
            self.session.delete(probe)

        return True
コード例 #8
0
 def get_probe_data(self, probe_id):
     """Return a dictionary containing all saved data about 'probe_id'"""
     probe = self.get_probe(probe_id)
     data = {
             'name': probe.name,
             'id': util.convert_mac(probe.custom_id, mode='display'),
             'storage_id': probe.custom_id,
             'location': probe.location,
             'scripts': self.get_script_data(probe),
             'network_configs': self.get_network_config_data(probe),
             'associated': probe.associated,
             'association_period_expired': probe.association_period_expired()
     }
     return data
コード例 #9
0
def register_key():
    """Takes an SSH public key, host key and a MAC, and registers
    it to the corresponding probe if a probe with that MAC has been added
    through the website.

    The function can give the following responses (with explanation):
        invalid-mac                 : The supplied MAC was invalid (in form)
        unknown-mac                 : The MAC was valid, but is not in the database
        invalid-pub-key             : The pub key was invalid (in form)
        invalid-host-key            : The host key was invalid (in form)
        already-registered          : There already exists keys associated with this MAC
        assocation-period-expired   : The assocation period has expired and needs
                                      to be renewed through the web site
        success                     : The keys were successfully registered/associated
                                      with the corresponding MAC address
    """
    mac = request.form.get('mac', '')
    if not util.is_mac_valid(mac):
        return 'invalid-mac'

    mac = util.convert_mac(mac, mode='storage')
    probe = database.get_probe(mac)

    if probe is None:
        return 'unknown-mac'

    pub_key = request.form.get('pub_key', '')
    host_key = request.form.get('host_key', '')

    if pub_key == '' or not util.is_pub_ssh_key_valid(pub_key):
        return 'invalid-pub-key'

    if host_key == '' or not util.is_ssh_host_key_valid(host_key):
        return 'invalid-host-key'

    if probe.pub_key != '' or probe.host_key != '':
        return 'already-registered'

    if probe.association_period_expired():
        return 'association-period-expired'

    probe.set_pub_key(pub_key)
    probe.set_host_key(host_key)
    probe.associated = True

    database.save_changes()
    ansible.export_known_hosts(database)

    return 'success'
コード例 #10
0
def get_ansible_status():
    """Return the status on the current ansible update

    The only argument is mac, which should be the probe's MAC address
    Returned statuses will be either:
        invalid-mac
        unknown-mac
        updating
        failed
        not-updated
        updated-{time of last update}
    """
    mac = request.args.get('mac', '')
    if mac == '':
        return 'invalid-mac'

    mac = util.convert_mac(mac, 'storage')
    probe = database.get_probe(mac)
    if probe is None:
        return 'unknown-mac'

    status = ansible.get_playbook_status(current_user.username, probe)
    if status in ['updating', 'failed']:
        return status

    if status == 'completed':
        probe.has_been_updated = True
        if (probe.last_updated is None or
            (datetime.today() - probe.last_updated).total_seconds() >= 60):
            probe.last_updated = datetime.today()
            database.save_changes()

    if status == 'completed' or probe.has_been_updated:
        if probe.last_updated is None:
            probe.last_updated = datetime.today()
            database.save_changes()
        time = util.get_textual_timedelta(datetime.today() -
                                          probe.last_updated)
        return 'updated-{}'.format(time)

    return 'not-updated'
コード例 #11
0
    def add_probe(self, username, probe_name, custom_id, location=None, scripts=None, network_configs=None):
        """Create a probe instance, add it to the database session, and return
        it to the caller"""
        if not self.is_valid_id(custom_id):
            return None

        port = self.generate_probe_port()
        if port == -1:
            print('Error generating port number. The port space may be '
                  'exhausted (though that is unlikely)')
            return None

        probe = Probe(probe_name, util.convert_mac(custom_id, mode='storage'),
                      location, port)
        user = self.get_user(username)
        user.probes.append(probe)

        if scripts is None:
            self.load_default_scripts(probe, username)

        if network_configs is None:
            self.load_default_network_configs(probe, username)

        return probe
コード例 #12
0
 def get_probe(self, probe_id):
     """Return the Probe class instance with the custom_id/MAC 'probe_id'"""
     probe_id = util.convert_mac(probe_id, mode='storage')
     return self.session.query(Probe).filter(Probe.custom_id == probe_id).first()
コード例 #13
0
def remove_host_config(probe_id):
    """Remove all Ansible configs associated with 'probe_id'"""
    probe_id = util.convert_mac(probe_id, mode='storage')
    dir_path = os.path.join(settings.ANSIBLE_PATH, 'host_vars', probe_id)
    if os.path.isdir(dir_path):
        shutil.rmtree(dir_path)
コード例 #14
0
def export_host_config(probe_id, data, filename):
    """Export 'data' as a host/probe specific YAML config file under the name
    'filename' for the probe with 'probe_id' as custom id (a MAC)"""
    probe_id = util.convert_mac(probe_id, mode='storage')
    dir_path = os.path.join(settings.ANSIBLE_PATH, 'host_vars', probe_id)
    _write_config(dir_path, data, filename)