def setUp(self):
        self.ch = ConfigHolder()
        self.ch.set('serviceurl', endpoint)
        self.ch.set('verboseLevel', 3)

        self.client = Client(self.ch)
        self.client.login(username, password)
        self.ch.set('endpoint', endpoint)
        self.ch.set('session', self.client.get_session())
Example #2
0
def ss_get(param, ignore_abort=False, timeout=30, no_block=False):
    """Returns None if parameter is not set.
    Raises Exceptions.NotFoundError if parameter doesn't exist.
    """
    ch = ConfigHolder(config={'foo': None})
    ch.set('ignoreAbort', ignore_abort)
    ch.set('noBlock', no_block)
    ch.set('timeout', timeout)
    client = Client(ch)
    return client.getRuntimeParameter(param)
Example #3
0
def get_rtp_all(side_effect, no_block=False):
    ch = ConfigHolder()
    ch.set('noBlock', no_block)
    ch.set('timeout', 1)
    ch.set('verboseLevel', 3)
    ch.set('endpoint', 'https://foo.bar')
    Client._getRuntimeParameter = Mock(side_effect=side_effect)
    client = Client(ch)
    client.httpClient.getRuntimeParameter = Mock(side_effect=side_effect)
    return client.get_rtp_all('foo', 'bar')
Example #4
0
    def doWork(self):
        ch = ConfigHolder(self.options)
        client = Client(ch)

        if self.options.cancel:
            client.cancel_abort()
        else:
            value = truncate_middle(Client.VALUE_LENGTH_LIMIT, self.reason,
                                    '\n(truncated)\n')
            client.setRuntimeParameter(NodeDecorator.ABORT_KEY, value)
Example #5
0
    def doWork(self):

        rvalue = ''.join([random.choice(string.ascii_letters + string.digits)
                          for _ in xrange(self.size)])

        if self.key is not None:
            ch = ConfigHolder(self.options)
            client = Client(ch)
            client.setRuntimeParameter(self.key, rvalue)

        print(rvalue)
Example #6
0
    def test_do_not_qualify_parameter(self):
        orch_node_name = NodeDecorator.orchestratorName + '-cloudX'
        orch_param = orch_node_name + \
                     NodeDecorator.NODE_PROPERTY_SEPARATOR + \
                     'foo'

        context = {NodeDecorator.NODE_INSTANCE_NAME_KEY: orch_node_name}
        ch = ConfigHolder(context=context,
                          config={
                              'bar': 'baz',
                              'endpoint': 'https://foo.bar'
                          })
        c = Client(ch)
        assert orch_param == c._qualifyKey(orch_param)
    def setUp(self):
        self.ch = ConfigHolder()
        self.ch.set('serviceurl', endpoint)
        self.ch.set('verboseLevel', 3)

        self.client = Client(self.ch)
        self.client.login(username, password)
        self.ch.set('endpoint', endpoint)
        self.ch.set('session', self.client.get_session())
Example #8
0
    def test_constructor(self):
        ch = ConfigHolder()
        ch.context = {}
        ch.options = {}
        ch.config = {}
        Client(ch)

        ch.context = {}
        ch.options = {}
        ch.config = {'endpoint': 'foo/bar'}
        c = Client(ch)
        assert c.ch.endpoint == c.ch.serviceurl == 'foo/bar'

        ch.context = {}
        ch.options = {}
        ch.config = {'serviceurl': 'bar/baz'}
        c = Client(ch)
        assert c.ch.serviceurl == 'bar/baz'
        assert not hasattr(c.ch, 'endpoint')
class TestResultArchiver(unittest.TestCase):

    def setUp(self):
        self.ch = ConfigHolder()
        self.ch.set('serviceurl', endpoint)
        self.ch.set('verboseLevel', 3)

        self.client = Client(self.ch)
        self.client.login(username, password)
        self.ch.set('endpoint', endpoint)
        self.ch.set('session', self.client.get_session())

    def tearDown(self):
        shutil.rmtree(run_uuid, ignore_errors=True)
        try: self.client.logout()
        except: pass

    @unittest.skipIf(not all([username, password, run_uuid]),
                     "Live test. Creds not set.")
    def test_get_reports(self):
        rg = ReportsGetter(self.ch)
        rg.get_reports(run_uuid)
        self.assertTrue(os.path.isdir(run_uuid))
class TestResultArchiver(unittest.TestCase):
    def setUp(self):
        self.ch = ConfigHolder()
        self.ch.set('serviceurl', endpoint)
        self.ch.set('verboseLevel', 3)

        self.client = Client(self.ch)
        self.client.login(username, password)
        self.ch.set('endpoint', endpoint)
        self.ch.set('session', self.client.get_session())

    def tearDown(self):
        shutil.rmtree(run_uuid, ignore_errors=True)
        try:
            self.client.logout()
        except:
            pass

    @unittest.skipIf(not all([username, password, run_uuid]),
                     "Live test. Creds not set.")
    def test_get_reports(self):
        rg = ReportsGetter(self.ch)
        rg.get_reports(run_uuid)
        self.assertTrue(os.path.isdir(run_uuid))
Example #11
0
    def doWork(self):
        ch = ConfigHolder(self.options)
        client = Client(ch)

        if self.options.cancel:
            client.cancel_abort()
        else:
            value = truncate_middle(Client.VALUE_LENGTH_LIMIT, self.reason,
                                    '\n(truncated)\n')
            client.setRuntimeParameter(NodeDecorator.ABORT_KEY, value)
 def _get_config_from_server(self):
     ch = ConfigHolder(options=self.options,
                       context={'foo': 'bar'},
                       config={'verboseLevel': self.verboseLevel})
     client = Client(ch)
     return client.get_server_configuration()
Example #13
0
    def doWork(self):
        ch = ConfigHolder(self.options)
        client = Client(ch)

        client.terminateRun()
Example #14
0
 def doWork(self):
     ch = ConfigHolder(self.options, context={'empty': None}, config={'empty': None})
     client = Client(ch)
     client.login(self.username, self.password)
Example #15
0
 def _get_client(self):
     ch = ConfigHolder(self.options)
     return Client(ch)
Example #16
0
class MainProgram(CommandBase):
    '''A command-line program to execute a run of creating a new machine.'''

    REF_QNAME = 'refqname'
    DEAFULT_WAIT = 0  # minutes
    DEFAULT_SLEEP = 30  # seconds
    INITIAL_SLEEP = 10  # seconds
    INITIAL_STATE = 'Inactive'

    def __init__(self, argv=None):
        self.moduleUri = None
        self.username = None
        self.password = None
        self.cookie = None
        self.endpoint = None
        self.parameters = {}
        super(MainProgram, self).__init__(argv)

    def parse(self):
        usage = '''usage: %prog [options] <module-url>

<module-uri>    Full URL to the module to execute.
                For example Public/Tutorials/HelloWorld/client_server'''

        self.parser.usage = usage

        self.parser.add_option('-u', '--username', dest='username',
                               help='SlipStream username', metavar='USERNAME',
                               default=os.environ.get('SLIPSTREAM_USERNAME'))
        self.parser.add_option('-p', '--password', dest='password',
                               help='SlipStream password', metavar='PASSWORD',
                               default=os.environ.get('SLIPSTREAM_PASSWORD'))

        self.parser.add_option('--cookie', dest='cookieFilename',
                               help='SlipStream cookie', metavar='FILE',
                               default=default_cookie)

        self.parser.add_option('--endpoint', dest='endpoint',
                               help='SlipStream server endpoint', metavar='URL',
                               default=default_endpoint)

        self.parser.add_option('--parameters', dest='parameters',
                               help='Deployment or image parameters override. '
                                    'The key must be in a form: '
                                    '<node-name>:<parameter-name>. '
                                    'Several pairs can be provided comma '
                                    'separated.',
                               metavar="KEY1=VALUE1,KEY2=VALUE2",
                               default='')

        self.parser.add_option('-w', '--wait', dest='wait',
                               help='Wait MINUTES for the deployment to finish.',
                               type='int', metavar='MINUTES',
                               default=self.DEAFULT_WAIT)

        self.parser.add_option('--nagios', dest='nagios',
                               help='Behave like Nagios check.',
                               default=False, action='store_true')

        self.options, self.args = self.parser.parse_args()

        self._checkArgs()

        self.resourceUrl = self.args[0]

    def _checkArgs(self):
        if len(self.args) < 1:
            self.parser.error('Missing resource-uri')
        if len(self.args) > 1:
            self.usageExitTooManyArguments()
        self.parameters = self._parseParameters()
        if self.options.nagios:
            self.options.verboseLevel = 0

    def _parseParameters(self):
        parameters = {}
        if not self.options.parameters:
            return parameters
        for pair in self.options.parameters.split(','):
            parts = pair.split('=')
            if len(parts) != 2:
                self.parser.error('Invalid parameter key/value pair: ' + pair)
            key, value = map(lambda x: x.strip(), parts)
            parameters[key] = value
        return parameters

    def _init_client(self):
        configHolder = ConfigHolder(self.options, context={'empty': None},
                                    config={'empty': None})
        configHolder.set('serviceurl', self.options.endpoint)
        self.client = Client(configHolder)

    def _launch_deployment(self):
        params = self._assembleData()
        return self.client.launchDeployment(params)

    def doWork(self):
        self._init_client()
        run_url = self._launch_deployment()
        if self._need_to_wait():
            self._wait_run_in_final_state(run_url)
        else:
            print(run_url)

    def _assembleData(self):
        self.parameters[self.REF_QNAME] = 'module/' + self.resourceUrl
        return [self._decorateKey(k) + '=' + v for k, v in self.parameters.items()]

    def _decorateKey(self, key):
        if key == self.REF_QNAME:
            return key
        parts = key.split(':')
        if len(parts) != 2:
            self.parser.error('Invalid key format: ' + key)
        nodename, key = parts
        return 'parameter--node--' + nodename + '--' + key

    def _wait_run_in_final_state(self, run_url):
        def _sleep():
            time_sleep = self.DEFAULT_SLEEP
            if _sleep.ncycle <= 2:
                if _sleep.ncycle == 1:
                    time_sleep = self.INITIAL_SLEEP
                elif _sleep.ncycle == 2:
                    time_sleep = self.DEFAULT_SLEEP - self.INITIAL_SLEEP
                _sleep.ncycle += 1
            time.sleep(time_sleep)
        _sleep.ncycle = 1

        run_uuid = run_url.rsplit('/', 1)[-1]
        time_end = time.time() + self.options.wait * 60
        state = self.INITIAL_STATE
        CRITICAL = self.options.nagios and 2 or 1
        while time.time() <= time_end:
            _sleep()
            try:
                state = self.client.getRunState(run_uuid, ignoreAbort=False)
            except Exceptions.AbortException as ex:
                if self.options.nagios:
                    print('CRITICAL - %s. State: %s. Run: %s' % (
                        str(ex).split('\n')[0], state, run_url))
                    sys.exit(CRITICAL)
                else:
                    raise ex
            if state == 'Terminal':
                print('OK - Terminal. Run: %s' % run_url)
                sys.exit(0)
            curr_time = time.strftime("%Y-%M-%d-%H:%M:%S UTC", time.gmtime())
            if not self.options.nagios:
                print("[%s] State: %s" % (curr_time, state))
        print("CRITICAL - Timed out after %i min. State: %s. Run: %s" % (
            self.options.wait, state, run_url))
        sys.exit(CRITICAL)

    def _need_to_wait(self):
        return self.options.wait > self.DEAFULT_WAIT
Example #17
0
 def doWork(self):
     configHolder = ConfigHolder(self.options)
     client = Client(configHolder)
     client.setRuntimeParameter('statecustom', self.value)
Example #18
0
 def doWork(self):
     ch = ConfigHolder(self.options)
     client = Client(ch)
     value = client.getRuntimeParameter(self.key)
     print(value if value is not None else '')
 def _get_config_from_server(self):
     ch = ConfigHolder(options=self.options, context={'foo': 'bar'},
                       config={'verboseLevel': self.verboseLevel})
     client = Client(ch)
     return client.get_server_configuration()
Example #20
0
 def doWork(self):
     ch = ConfigHolder(self.options)
     client = Client(ch)
     value = client.getRuntimeParameter(self.key)
     print(value if value is not None else '')
Example #21
0
 def doWork(self):
     ch = ConfigHolder(self.options)
     client = Client(ch)
     client.logout()
    def doWork(self):
        ch = ConfigHolder(self.options)
        client = Client(ch)

        client.cancel_abort()
Example #23
0
    def doWork(self):
        ch = ConfigHolder(self.options)
        client = Client(ch)

        client.cancel_abort()
Example #24
0
 def doWork(self):
     ch = ConfigHolder(self.options)
     client = Client(ch)
     client.setRuntimeParameter(self.key, self.value)
Example #25
0
class MainProgram(CommandBase):
    """A command-line program to execute a run of creating a new machine."""

    RUN_TYPE = 'type'
    BYPASS_SSH_CHECK = 'bypass-ssh-check'
    REF_QNAME = util.RUN_PARAM_REFQNAME
    RUN_LAUNCH_NOT_NODE_PARAMS = (RUN_TYPE,
                                  BYPASS_SSH_CHECK,
                                  util.RUN_PARAM_REFQNAME,
                                  util.RUN_PARAM_MUTABLE,
                                  util.RUN_PARAM_KEEP_RUNNING,
                                  util.RUN_PARAM_TAGS)
    DEFAULT_WAIT = 0  # minutes
    DEFAULT_SLEEP = 30  # seconds
    INITIAL_SLEEP = 10  # seconds
    INITIAL_STATE = RUN_STATES[0]
    FINAL_STATES = FINAL_STATES

    def __init__(self, argv=None):
        self.moduleUri = None
        self.endpoint = None
        self.parameters = {}
        super(MainProgram, self).__init__(argv)

    def parse(self):
        usage = '''usage: %prog [options] <module-url>

<module-uri>    Full URL to the module to execute.
                For example Public/Tutorials/HelloWorld/client_server'''

        self.parser.usage = usage

        self.addEndpointOption()

        self.parser.add_option('--parameters', dest='parameters',
                               help='Deployment or image parameters override. '
                                    'The key must be in a form: '
                                    '<node-name>:<parameter-name> (for deployment) '
                                    'or <parameter-name> (for image). '
                                    'Several pairs can be provided comma '
                                    'separated.',
                               metavar="KEY1=VALUE1,KEY2=VALUE2",
                               default='')

        self.parser.add_option('-w', '--wait', dest='wait',
                               help='Wait MINUTES for the deployment to finish.',
                               type='int', metavar='MINUTES',
                               default=self.DEFAULT_WAIT)

        self.parser.add_option('--nagios', dest='nagios',
                               help='Behave like Nagios check.',
                               default=False, action='store_true')

        self.parser.add_option('--kill-vms-on-error',
                               dest='kill_vms_on_error',
                               help='Kill VMs on any error.',
                               default=False, action='store_true')

        self.parser.add_option('--scalable',
                               dest='scalable',
                               help='Launch a scalable application.',
                               default=False, action='store_true')

        self.parser.add_option('--check-ssh-key',
                               dest='bypass_ssh_check',
                               help="Check if there is an SSH key in the user profile",
                               default=True, action='store_false')

        self.parser.add_option('--keep-running',
                               dest='keep_running',
                               help="Define when the application should be kept running. \n" + \
                                    "Available values: never, always, on-error, on-success. \n" + \
                                    "If not set the user default will be used.",
                               default='')

        self.parser.add_option('--build-image',
                               dest='build_image',
                               help='Build the image instead of running it',
                               default=False, action='store_true')

        self.parser.add_option('--final-states', dest='final_states',
                               help='Comma separated list of final states. ' +
                                    'Default: %s' % ', '.join(self.FINAL_STATES),
                               type='string', action="callback",
                               callback=self._comma_separ_to_list_callback,
                               metavar='FINAL_STATES', default=self.FINAL_STATES)

        self.parser.add_option('--get-reports-all', dest='get_reports_all',
                               help='Get all reports after final state is reached.',
                               default=False, action='store_true')

        self.parser.add_option('--get-reports', dest='reports_components',
                               help='Comma separated list of components to download reports for. '
                                    'Example: nginx,worker.1,worker.3 - will download reports for all component '
                                    'instances of nginx and only for instances 1 and 3 of worker.',
                               type='string', action="callback",
                               callback=self._comma_separ_to_list_callback, default='')

        self.parser.add_option('--get-reports-dir', dest='output_dir',
                               help='Path to the directory to store the reports. '
                                    'Default: <working directory>/<run-uuid>.',
                               default=os.getcwd())

        self.options, self.args = self.parser.parse_args()

        self._checkArgs()

        self.resourceUrl = self.args[0]

    @staticmethod
    def _comma_separ_to_list_callback(option, opt, value, parser):
        setattr(parser.values, option.dest, value.split(','))

    def _checkArgs(self):
        if len(self.args) < 1:
            self.parser.error('Missing resource-uri')
        if len(self.args) > 1:
            self.usageExitTooManyArguments()
        self.parameters = self._parseParameters()
        if self.options.nagios:
            self.options.verboseLevel = 0

    def _parseParameters(self):
        parameters = {}
        if not self.options.parameters:
            return parameters
        for pair in self.options.parameters.split(','):
            parts = pair.split('=', 1)
            if len(parts) != 2:
                self.parser.error('Invalid parameter key/value pair: ' + pair)
            key, value = map(lambda x: x.strip(), parts)
            parameters[key] = value
        return parameters

    def doWork(self):
        self._init_client()
        run_url = self._launch_deployment()
        if self._need_to_wait():
            rc = self._get_critical_rc()
            try:
                rc = self._wait_run_and_handle_failures(run_url)
                sys.exit(rc)
            finally:
                self._cond_terminate_run(rc, run_url)
                self._download_reports(self.client.get_api(), run_url)
        else:
            print(run_url)

    def _init_client(self):
        configHolder = ConfigHolder(self.options, context={'empty': None},
                                    config={'empty': None})
        configHolder.set('serviceurl', self.options.endpoint)
        self.client = Client(configHolder)

    def _launch_deployment(self):
        """Return run URL on success.
        On failure:
        - in case of Nagios check generate CRITICAL error
        - else, the caught exception is re-raised.
        """
        params = self._assembleData()
        try:
            return self.client.launchDeployment(params)
        except Exception as ex:
            if self.options.nagios:
                print("CRITICAL - Unhandled error: %s." % (str(ex).split('\n')[0]))
                sys.exit(RC_CRITICAL_NAGIOS)
            else:
                raise

    def _wait_run_and_handle_failures(self, run_url):
        """Wait for final state of the run. Handle failures and print
        respective messages. Return global exit code depending if this is
        Nagios check or not.
        """
        rc = self._get_critical_rc()

        try:
            reached_state = self._wait_run_in_states(run_url,
                                                     self.options.wait,
                                                     self.options.final_states)
        except AbortException as ex:
            if self.options.nagios:
                print('CRITICAL - %s. State: %s. Run: %s' % (
                    str(ex).split('\n')[0], ex.state, run_url))
            else:
                print('CRITICAL - %s\nState: %s. Run: %s' % (
                    str(ex), ex.state, run_url))
            ss_abort_msg = self.client.getGlobalAbortMessage()
            print('Abort reason:\n%s' % ss_abort_msg)
        except TimeoutException as ex:
            print("CRITICAL - Timed out after %i min. State: %s. Run: %s" % (
                self.options.wait, ex.state, run_url))
        except Exception as ex:
            if self.options.nagios:
                print("CRITICAL - Unhandled error: %s. Run: %s" % (
                    str(ex).split('\n')[0], run_url))
                traceback.print_exc()
            else:
                raise
        else:
            print('OK - State: %s. Run: %s' % (reached_state, run_url))
            rc = RC_SUCCESS

        return rc

    def _cond_terminate_run(self, returncode, run_url):
        """Run gets conditionally terminated
        - when we are acting as Nagios check
        - when there was a failure and we were asked to kill the VMs on error.

        Before termination, in case the abort flag was raised, we wait for reports
        uploaded from components, by waiting for any state after SendingReports.
        """

        # In case abort message is set, server-side Sate Machine will attempt
        # to advance the run through all the states up to Aborted.
        # This ensures that reports get uploaded by the components.
        if returncode != RC_SUCCESS:
            self._wait_reports_sent_if_run_aborted(run_url)

        if self.options.nagios or \
                (returncode != RC_SUCCESS and self.options.kill_vms_on_error):
            self._terminate_run()

    def _wait_reports_sent_if_run_aborted(self, run_url):
        if self._is_run_aborted(run_url):
            print_step("Abort flag was raised. Waiting for reports to be uploaded from components.")
            try:
                self._wait_run_in_states(run_url, 2, run_states_after('SendingReports'),
                                         ignore_abort=True)
            except TimeoutException:
                pass

    def _is_run_aborted(self, run_url):
        return self.client.is_run_aborted(run_url_to_uuid(run_url))

    def _terminate_run(self):
        print_step('Terminating run.')
        try:
            self.client.terminateRun()
        except:
            pass

    def _get_critical_rc(self):
        return self.options.nagios and RC_CRITICAL_NAGIOS or RC_CRITICAL_DEFAULT

    def _assembleData(self):
        self._add_not_node_params()
        return self._decorate_parameters(self.parameters,
                                         filter_out=self.RUN_LAUNCH_NOT_NODE_PARAMS)

    def _add_not_node_params(self):
        self.parameters[self.REF_QNAME] = 'module/' + self.resourceUrl

        if self.options.build_image:
            self.parameters[self.RUN_TYPE] = 'Machine'

        if self.options.scalable:
            self.parameters[util.RUN_PARAM_MUTABLE] = 'true'
            
        if self.options.bypass_ssh_check:
            self.parameters[self.BYPASS_SSH_CHECK] = 'true'
            
        if self.options.keep_running:
            self.parameters[util.RUN_PARAM_KEEP_RUNNING] = self.options.keep_running

    def _decorate_node_param_key(self, key, filter_out=[]):
        if key in filter_out:
            return key
        parts = key.split(':')
        if len(parts) == 1:
            key = parts[0]
            return 'parameter--' + key
        elif len(parts) == 2:
            nodename, key = parts
            return 'parameter--node--' + nodename + '--' + key
        else:
            self.parser.error('Invalid key format: ' + key)

    def _decorate_parameters(self, params, filter_out=[]):
        return ['%s=%s' % (self._decorate_node_param_key(k, filter_out), v)
                for k, v in params.items()]

    def _wait_run_in_states(self, run_url, waitmin, final_states, ignore_abort=False):
        """Return on reaching one of the requested state.
        On timeout raise TimeoutException with the last state attribute set.
        On aborted Run by default raise AbortException with the last state attribute set.
        """
        def _sleep():
            time_sleep = self.DEFAULT_SLEEP
            if _sleep.ncycle <= 2:
                if _sleep.ncycle == 1:
                    time_sleep = self.INITIAL_SLEEP
                elif _sleep.ncycle == 2:
                    time_sleep = self.DEFAULT_SLEEP - self.INITIAL_SLEEP
                _sleep.ncycle += 1
            time.sleep(time_sleep)
        _sleep.ncycle = 1

        if not self.options.nagios:
            print_step('Waiting %s min for Run %s to reach %s' % \
                       (waitmin, run_url, ','.join(final_states)))

        run_uuid = run_url_to_uuid(run_url)
        time_end = time.time() + waitmin * 60
        state = self.INITIAL_STATE
        while time.time() <= time_end:
            _sleep()
            try:
                state = self.client.getRunState(run_uuid, ignoreAbort=ignore_abort)
            except AbortException as ex:
                ex.state = self.client.getRunState(run_uuid, ignoreAbort=True)
                raise
            if state in final_states:
                return state
            if not self.options.nagios:
                curr_time = time.strftime("%Y-%M-%d-%H:%M:%S UTC", time.gmtime())
                print("[%s] State: %s" % (curr_time, state))
        time_exc = TimeoutException('Timed out.')
        time_exc.state = state
        raise time_exc

    def _need_to_wait(self):
        return self.options.wait > self.DEFAULT_WAIT

    def _download_reports(self, api, run_url):
        if not (self.options.reports_components or self.options.get_reports_all):
            return

        components = []
        if self.options.reports_components:
            components = self.options.reports_components
        ch = ConfigHolder(options=self.options)
        rg = ReportsGetter(api, ch)
        rg.get_reports(run_url_to_uuid(run_url), components=components)
Example #26
0
 def doWork(self):
     configHolder = ConfigHolder(self.options)
     client = Client(configHolder)
     value = client.getRuntimeParameter(self.key)
     print value
Example #27
0
 def _init_client(self):
     configHolder = ConfigHolder(self.options, context={'empty': None},
                                 config={'empty': None})
     configHolder.set('serviceurl', self.options.endpoint)
     self.client = Client(configHolder)
Example #28
0
 def _init_client(self):
     configHolder = ConfigHolder(self.options,
                                 context={'empty': None},
                                 config={'empty': None})
     configHolder.set('serviceurl', self.options.endpoint)
     self.client = Client(configHolder)
Example #29
0
 def doWork(self):
     ch = ConfigHolder(self.options,
                       context={'empty': None},
                       config={'empty': None})
     client = Client(ch)
     client.login(self.username, self.password)
Example #30
0
class MainProgram(CommandBase):
    """A command-line program to execute a run of creating a new machine."""

    RUN_TYPE = 'type'
    BYPASS_SSH_CHECK = 'bypass-ssh-check'
    REF_QNAME = util.RUN_PARAM_REFQNAME
    RUN_LAUNCH_NOT_NODE_PARAMS = (RUN_TYPE, BYPASS_SSH_CHECK,
                                  util.RUN_PARAM_REFQNAME,
                                  util.RUN_PARAM_MUTABLE,
                                  util.RUN_PARAM_KEEP_RUNNING,
                                  util.RUN_PARAM_TAGS)
    DEFAULT_WAIT = 0  # minutes
    DEFAULT_SLEEP = 30  # seconds
    INITIAL_SLEEP = 10  # seconds
    INITIAL_STATE = RUN_STATES[0]
    FINAL_STATES = FINAL_STATES

    def __init__(self, argv=None):
        self.moduleUri = None
        self.endpoint = None
        self.parameters = {}
        super(MainProgram, self).__init__(argv)

    def parse(self):
        usage = '''usage: %prog [options] <module-url>

<module-uri>    Full URL to the module to execute.
                For example Public/Tutorials/HelloWorld/client_server'''

        self.parser.usage = usage

        self.addEndpointOption()

        self.parser.add_option('--parameters',
                               dest='parameters',
                               help='Deployment or image parameters override. '
                               'The key must be in a form: '
                               '<node-name>:<parameter-name> (for deployment) '
                               'or <parameter-name> (for image). '
                               'Several pairs can be provided comma '
                               'separated.',
                               metavar="KEY1=VALUE1,KEY2=VALUE2",
                               default='')

        self.parser.add_option(
            '-w',
            '--wait',
            dest='wait',
            help='Wait MINUTES for the deployment to finish.',
            type='int',
            metavar='MINUTES',
            default=self.DEFAULT_WAIT)

        self.parser.add_option('--nagios',
                               dest='nagios',
                               help='Behave like Nagios check.',
                               default=False,
                               action='store_true')

        self.parser.add_option('--kill-vms-on-error',
                               dest='kill_vms_on_error',
                               help='Kill VMs on any error.',
                               default=False,
                               action='store_true')

        self.parser.add_option('--scalable',
                               dest='scalable',
                               help='Launch a scalable application.',
                               default=False,
                               action='store_true')

        self.parser.add_option(
            '--check-ssh-key',
            dest='bypass_ssh_check',
            help="Check if there is an SSH key in the user profile",
            default=True,
            action='store_false')

        self.parser.add_option('--keep-running',
                               dest='keep_running',
                               help="Define when the application should be kept running. \n" + \
                                    "Available values: never, always, on-error, on-success. \n" + \
                                    "If not set the user default will be used.",
                               default='')

        self.parser.add_option('--build-image',
                               dest='build_image',
                               help='Build the image instead of running it',
                               default=False,
                               action='store_true')

        self.parser.add_option('--final-states',
                               dest='final_states',
                               help='Comma separated list of final states. ' +
                               'Default: %s' % ', '.join(self.FINAL_STATES),
                               type='string',
                               action="callback",
                               callback=self._comma_separ_to_list_callback,
                               metavar='FINAL_STATES',
                               default=self.FINAL_STATES)

        self.parser.add_option(
            '--get-reports-all',
            dest='get_reports_all',
            help='Get all reports after final state is reached.',
            default=False,
            action='store_true')

        self.parser.add_option(
            '--get-reports',
            dest='reports_components',
            help='Comma separated list of components to download reports for. '
            'Example: nginx,worker.1,worker.3 - will download reports for all component '
            'instances of nginx and only for instances 1 and 3 of worker.',
            type='string',
            action="callback",
            callback=self._comma_separ_to_list_callback,
            default='')

        self.parser.add_option(
            '--get-reports-dir',
            dest='output_dir',
            help='Path to the directory to store the reports. '
            'Default: <working directory>/<run-uuid>.',
            default=os.getcwd())

        self.options, self.args = self.parser.parse_args()

        self._checkArgs()

        self.resourceUrl = self.args[0]

    @staticmethod
    def _comma_separ_to_list_callback(option, opt, value, parser):
        setattr(parser.values, option.dest, value.split(','))

    def _checkArgs(self):
        if len(self.args) < 1:
            self.parser.error('Missing resource-uri')
        if len(self.args) > 1:
            self.usageExitTooManyArguments()
        self.parameters = self._parseParameters()
        if self.options.nagios:
            self.options.verboseLevel = 0

    def _parseParameters(self):
        parameters = {}
        if not self.options.parameters:
            return parameters
        for pair in self.options.parameters.split(','):
            parts = pair.split('=', 1)
            if len(parts) != 2:
                self.parser.error('Invalid parameter key/value pair: ' + pair)
            key, value = map(lambda x: x.strip(), parts)
            parameters[key] = value
        return parameters

    def doWork(self):
        self._init_client()
        run_url = self._launch_deployment()
        if self._need_to_wait():
            rc = self._get_critical_rc()
            try:
                rc = self._wait_run_and_handle_failures(run_url)
                sys.exit(rc)
            finally:
                self._cond_terminate_run(rc, run_url)
                self._download_reports(self.client.get_api(), run_url)
        else:
            print(run_url)

    def _init_client(self):
        configHolder = ConfigHolder(self.options,
                                    context={'empty': None},
                                    config={'empty': None})
        configHolder.set('serviceurl', self.options.endpoint)
        self.client = Client(configHolder)

    def _launch_deployment(self):
        """Return run URL on success.
        On failure:
        - in case of Nagios check generate CRITICAL error
        - else, the caught exception is re-raised.
        """
        params = self._assembleData()
        try:
            return self.client.launchDeployment(params)
        except Exception as ex:
            if self.options.nagios:
                print("CRITICAL - Unhandled error: %s." %
                      (str(ex).split('\n')[0]))
                sys.exit(RC_CRITICAL_NAGIOS)
            else:
                raise

    def _wait_run_and_handle_failures(self, run_url):
        """Wait for final state of the run. Handle failures and print
        respective messages. Return global exit code depending if this is
        Nagios check or not.
        """
        rc = self._get_critical_rc()

        try:
            reached_state = self._wait_run_in_states(run_url,
                                                     self.options.wait,
                                                     self.options.final_states)
        except AbortException as ex:
            if self.options.nagios:
                print('CRITICAL - %s. State: %s. Run: %s' %
                      (str(ex).split('\n')[0], ex.state, run_url))
            else:
                print('CRITICAL - %s\nState: %s. Run: %s' %
                      (str(ex), ex.state, run_url))
            ss_abort_msg = self.client.getGlobalAbortMessage()
            print('Abort reason:\n%s' % ss_abort_msg)
        except TimeoutException as ex:
            print("CRITICAL - Timed out after %i min. State: %s. Run: %s" %
                  (self.options.wait, ex.state, run_url))
        except Exception as ex:
            if self.options.nagios:
                print("CRITICAL - Unhandled error: %s. Run: %s" %
                      (str(ex).split('\n')[0], run_url))
                traceback.print_exc()
            else:
                raise
        else:
            print('OK - State: %s. Run: %s' % (reached_state, run_url))
            rc = RC_SUCCESS

        return rc

    def _cond_terminate_run(self, returncode, run_url):
        """Run gets conditionally terminated
        - when we are acting as Nagios check
        - when there was a failure and we were asked to kill the VMs on error.

        Before termination, in case the abort flag was raised, we wait for reports
        uploaded from components, by waiting for any state after SendingReports.
        """

        # In case abort message is set, server-side Sate Machine will attempt
        # to advance the run through all the states up to Aborted.
        # This ensures that reports get uploaded by the components.
        if returncode != RC_SUCCESS:
            self._wait_reports_sent_if_run_aborted(run_url)

        if self.options.nagios or \
                (returncode != RC_SUCCESS and self.options.kill_vms_on_error):
            self._terminate_run()

    def _wait_reports_sent_if_run_aborted(self, run_url):
        if self._is_run_aborted(run_url):
            print_step(
                "Abort flag was raised. Waiting for reports to be uploaded from components."
            )
            try:
                self._wait_run_in_states(run_url,
                                         2,
                                         run_states_after('SendingReports'),
                                         ignore_abort=True)
            except TimeoutException:
                pass

    def _is_run_aborted(self, run_url):
        return self.client.is_run_aborted(run_url_to_uuid(run_url))

    def _terminate_run(self):
        print_step('Terminating run.')
        try:
            self.client.terminateRun()
        except:
            pass

    def _get_critical_rc(self):
        return self.options.nagios and RC_CRITICAL_NAGIOS or RC_CRITICAL_DEFAULT

    def _assembleData(self):
        self._add_not_node_params()
        return self._decorate_parameters(
            self.parameters, filter_out=self.RUN_LAUNCH_NOT_NODE_PARAMS)

    def _add_not_node_params(self):
        self.parameters[self.REF_QNAME] = 'module/' + self.resourceUrl

        if self.options.build_image:
            self.parameters[self.RUN_TYPE] = 'Machine'

        if self.options.scalable:
            self.parameters[util.RUN_PARAM_MUTABLE] = 'true'

        if self.options.bypass_ssh_check:
            self.parameters[self.BYPASS_SSH_CHECK] = 'true'

        if self.options.keep_running:
            self.parameters[
                util.RUN_PARAM_KEEP_RUNNING] = self.options.keep_running

    def _decorate_node_param_key(self, key, filter_out=[]):
        if key in filter_out:
            return key
        parts = key.split(':')
        if len(parts) == 1:
            key = parts[0]
            return 'parameter--' + key
        elif len(parts) == 2:
            nodename, key = parts
            return 'parameter--node--' + nodename + '--' + key
        else:
            self.parser.error('Invalid key format: ' + key)

    def _decorate_parameters(self, params, filter_out=[]):
        return [
            '%s=%s' % (self._decorate_node_param_key(k, filter_out), v)
            for k, v in params.items()
        ]

    def _wait_run_in_states(self,
                            run_url,
                            waitmin,
                            final_states,
                            ignore_abort=False):
        """Return on reaching one of the requested state.
        On timeout raise TimeoutException with the last state attribute set.
        On aborted Run by default raise AbortException with the last state attribute set.
        """
        def _sleep():
            time_sleep = self.DEFAULT_SLEEP
            if _sleep.ncycle <= 2:
                if _sleep.ncycle == 1:
                    time_sleep = self.INITIAL_SLEEP
                elif _sleep.ncycle == 2:
                    time_sleep = self.DEFAULT_SLEEP - self.INITIAL_SLEEP
                _sleep.ncycle += 1
            time.sleep(time_sleep)

        _sleep.ncycle = 1

        if not self.options.nagios:
            print_step('Waiting %s min for Run %s to reach %s' % \
                       (waitmin, run_url, ','.join(final_states)))

        run_uuid = run_url_to_uuid(run_url)
        time_end = time.time() + waitmin * 60
        state = self.INITIAL_STATE
        while time.time() <= time_end:
            _sleep()
            try:
                state = self.client.getRunState(run_uuid,
                                                ignoreAbort=ignore_abort)
            except AbortException as ex:
                ex.state = self.client.getRunState(run_uuid, ignoreAbort=True)
                raise
            if state in final_states:
                return state
            if not self.options.nagios:
                curr_time = time.strftime("%Y-%M-%d-%H:%M:%S UTC",
                                          time.gmtime())
                print("[%s] State: %s" % (curr_time, state))
        time_exc = TimeoutException('Timed out.')
        time_exc.state = state
        raise time_exc

    def _need_to_wait(self):
        return self.options.wait > self.DEFAULT_WAIT

    def _download_reports(self, api, run_url):
        if not (self.options.reports_components
                or self.options.get_reports_all):
            return

        components = []
        if self.options.reports_components:
            components = self.options.reports_components
        ch = ConfigHolder(options=self.options)
        rg = ReportsGetter(api, ch)
        rg.get_reports(run_url_to_uuid(run_url), components=components)
Example #31
0
def ss_set(key, value, ignore_abort=False):
    ch = ConfigHolder(config={'foo': None})
    ch.set('ignoreAbort', ignore_abort)
    client = Client(ch)
    client.setRuntimeParameter(key, value)
Example #32
0
 def doWork(self):
     ch = ConfigHolder(self.options)
     client = Client(ch)
     client.logout()