def rest_return_switch_dpid_from_ip(self, node, soft_error=False): ''' Objective: Returns switch DPID, given a switch alias Input: | `node` | Reference to node as defined in .topo file | Description: The function - executes a REST GET for http://<CONTROLLER_IP>:8082/api/v1/data/controller/core/switch?select=alias - and greps for switch-alias, and returns switch-dpid Return value - Switch DPID on success - False on failure ''' try: t = test.Test() c = t.controller('master') url_to_get = '/api/v1/data/controller/core/switch' c.rest.get(url_to_get) switch = t.switch(node) except: helpers.test_error("URL Get Failed", soft_error) return False else: content = c.rest.content() for x in range(0, len(content)): if content[x].has_key('inet-address'): if str(content[x]['inet-address']['ip']) == switch.ip(): return content[x]['dpid'] else: helpers.log("Looks like %s is a disconnected switch" % (content[x]['dpid'])) return False
def bash_delete_tag(self, node, intf, soft_error=True): """ Function to remove the vlan tag from the host eth interfaces. Note: soft_error=True because in the common use case, we just want to log the error but not trigger failure. """ t = test.Test() n = t.node(node) try: n.sudo("vconfig rem %s" % intf) except: output = helpers.exception_info_value() helpers.log("Output: %s" % output) # Catch error: # ERROR: trying to remove VLAN -:eth1.20:- error: No such device if helpers.any_match(str(output), r'error: No such devices'): helpers.test_error( "vconfig rem error - no such device '%s'" % intf, soft_error) return False else: helpers.test_error( 'Uncaught exception:\n%s' % helpers.exception_info(), soft_error) return False return True
def cli_boot_factory_default(self, node, timeout=360): """ Runs boot factory-default. This will cause the SSH connection to disappear and the session would need to be restarted. """ t = test.Test() n = t.node(node) if helpers.is_bigtap(n.platform()): helpers.log("Boot factory-default on '%s' (Big Tap Controller)" % node) n.enable("boot factory-default", prompt=r'Do you want to continue \[no\]\? ') n.enable("yes", prompt='Enter NEW admin password: '******'Repeat NEW admin password: '******'UNAVAILABLE localhost') elif helpers.is_bvs(n.platform()): helpers.log("Boot factory-default on '%s' (BVS)" % node) helpers.summary_log( 'BVS boot factory may take a bit of time. Setting timeout to %s seconds.' % timeout) # vui-bvs> enable # vui-bvs# boot factory-default # boot factory default: will over-write the alternate partition # proceed ("yes" or "y" to continue): y # boot factory default: loading image into stage partition # boot factory default: checking integrity of new partition # boot factory default: New Partition Ready # factory default: ready for reboot # boot factory default: reboot? ("yes" or "y" to continue): y # # Broadcast message from root@blah # (unknown) at 20:32 ... # # The system is going down for reboot NOW! # Connection to 10.192.104.2 closed by remote host. # Connection to 10.192.104.2 closed. n.enable('') n.send('boot factory-default') n.expect(r'proceed \("y" or "yes" to continue\)') n.send('y') n.expect(r'copying image into alternate partition', timeout=timeout) n.expect(r'checking integrity of new partition', timeout=timeout) n.expect(r'New Partition Ready', timeout=timeout) n.expect(r'ready for reboot', timeout=timeout) n.expect(r'"y" or "yes" to continue\): ', timeout=timeout) n.send('y') # n.expect(r'system is going down for reboot') helpers.summary_log("'%s' has been rebooted." % node) else: helpers.test_error( "Boot factory-default is only supported on 'bvs' and 'bigtap'") # At this point, device is rebooted and we lose the session handle. # Connect to device console to complete first-boot. helpers.log( "Boot factory-default completed on '%s'. System should be rebooting." % node) return True
def bash_init_intf(self, node, intf): t = test.Test() n = t.node(node) try: n.sudo("ifconfig %s 0.0.0.0" % intf) except: helpers.test_error("Ignore Host errors", soft_error=True) return True
def bash_ping6(self, node=None, dest_ip=None, dest_node=None, return_stats=False, *args, **kwargs): """ Perform a ping6 from the shell. Returns the loss percentage - 0 - 0% loss (default) - 100 - 100% loss (default) - Stats dict if return_stats is ${true} Inputs: - node: The device name as defined in the topology file, e.g., 'c1', 's1', etc. - dest_ip: Ping6 this destination IP address - dest_node Ping6 this destination node ('c1', 's1', etc) - source_if: Source interface - count: Number of ping6 packets to send - ttl: IP Time-to-live - record_route: ${true} - to include RECORD ROUTE option - interval: Time in seconds (floating point value allowed) to wait between sending packets. Example: | ${lossA} = | Bash Ping6 | h1 | 10.192.104.1 | source_if=eth1 | | ${lossB} = | Bash Ping6 | node=master | dest_node=s1 | | => - ${lossA} = 0 - ${lossB} = 100 Miscellaneous: - See also Controller.cli ping6 - See also autobot.helpers.__init__.py to see what Unix ping6 command option is used for each input parameter. """ t = test.Test() n = t.node(node) if not dest_ip and not dest_node: helpers.test_error("Must specify 'dest_ip' or 'dest_node'") if dest_ip and dest_node: helpers.test_error("Specify 'dest_ip' or 'dest_node' but not both") if dest_ip: dest = dest_ip if dest_node: dest = t.node(dest_node).ip() stats = helpers._ping6(dest, node_handle=n, mode='bash', *args, **kwargs) if kwargs.get('background', False): return stats elif return_stats: return stats else: return stats["packets_loss_pct"]
def bash_run_command(self, node, cmd): t = test.Test() n = t.node(node) try: content = n.bash("%s " % cmd)['content'] str_list = helpers.strip_cli_output(content, to_list=True) except: helpers.test_error("Bash run command failed", soft_error=True) str_list = "Bash Run Command Failed" return str_list
def bash_get_distributor(self, node, soft_error=False): """ Return the distributor id: Ubuntu """ t = test.Test() n = t.node(node) content = n.bash("lsb_release -i")['content'] match = re.search(r'Distributor ID:\s+(.*)', content, re.M) if match: return match.group(1) else: helpers.test_error("lsb_release command output is invalid", soft_error=soft_error)
def console(self, driver=None, force_reconnect=False, expect_console_banner=False): if self.dev_console and not force_reconnect: return self.dev_console else: # helpers.log("Connecting to console for node '%s'" % self.name()) pass super(HostNode, self).console(driver) if self._console_info['type'] in ['telnet', 'libvirt']: # For telnet console, requirements are an IP address and a port # number. # # For libvirt console, requirements are an IP address (of the # KVM server) and the libvirt VM name (libvirt_vm_name). We will # first SSH to the KVM server, then execute 'virsh console <name>'. self.dev_console = devconf.HostDevConf( name=self.name() + "_console", host=self._console_info['ip'], port=self._console_info['port'], user=self._console_info['user'], password=self._console_info['password'], protocol=self._console_info['protocol'], console_info=self._console_info, debug=self.dev_debug_level) else: helpers.test_error("Unsupported console type '%s'" % self._console_info['type']) if expect_console_banner: self._match_console_banner() if self._console_info['type'] == 'libvirt': self.dev_console.send("virsh console %s" % self._console_info['libvirt_vm_name']) # FIXME!!! The code below is not working. Figure out why... # if self._console_info['driver']: # helpers.log("Setting devconf driver for console to '%s'" # % self._console_info['driver']) # self.dev_console.conn.set_driver(self._console_info['driver']) return self.dev_console
def mininet_ping(self, src, dst, count=5): t = test.Test() mn = t.mininet() mn.cli('%s ping %s -c %s' % (src, dst, count)) out = mn.cli_content() unreachable = helpers.any_match(out, r'is unreachable') if unreachable: helpers.log("Network is unreachable. Assuming 100% packet loss.") return 100 loss = helpers.any_match(out, r', (\d+)% packet loss') if loss: helpers.log("packet loss: %s" % loss) return loss[0] helpers.test_error("Uncaught condition")
def bash_lsb_release(self, node, minor=False, soft_error=False): """ Return the Ubuntu release number. Ubuntu release numbers typically has the format "14.04" or "12.04". - By default, return the major version number, e.g., 14 or 12. - If minor=True, return the minor version number, e.g., 0.3 or 0.4. """ t = test.Test() n = t.node(node) content = n.bash("lsb_release -r")['content'] match = re.search(r'Release:\s+(\d+)\.(\d+)', content, re.M) if match: if minor: return int(match.group(2)) else: return int(match.group(1)) else: helpers.test_error("lsb_release command output is invalid", soft_error=soft_error)
def cli_ping(self, node, dest_ip=None, dest_node=None, return_stats=False, *args, **kwargs): """ Perform a ping from the CLI. Returns the loss percentage - 0 - 0% loss (default) - 100 - 100% loss (default) - Stats dict if return_stats is ${true} Inputs: - node: The device name as defined in the topology file, e.g., 'c1', 's1', etc. - dest_ip: Ping this destination IP address - dest_node Ping this destination node ('c1', 's1', etc) Example: | ${lossA} = | Cli Ping | h1 | 10.192.104.1 | | ${lossB} = | Cli Ping | node=master | dest_node=s1 | => - ${lossA} = 0 - ${lossB} = 100 See also Host.bash ping. """ t = test.Test() n = t.node(node) if not dest_ip and not dest_node: helpers.test_error("Must specify 'dest_ip' or 'dest_node'") if dest_ip and dest_node: helpers.test_error("Specify 'dest_ip' or 'dest_node' but not both") if dest_ip: dest = dest_ip if dest_node: dest = t.node(dest_node).ip() stats = helpers._ping(dest, node_handle=n, mode='cli', *args, **kwargs) if return_stats: return stats else: return stats["packets_loss_pct"]
def http_request(self, *args, **kwargs): retries = int(kwargs.pop('retries', 0)) sleep_time = float(kwargs.pop('sleep_time_between_retries', 10)) while True: try: result = self._http_request(*args, **kwargs) except: helpers.log('HTTP request error:\n%s' % helpers.exception_info()) if retries > 0: helpers.log( 'Retrying HTTP request in %s seconds (retries=%s)' % (sleep_time, retries)) retries -= 1 helpers.sleep(sleep_time) else: raise else: if int(result['status_code']) == 401: if self.session_cookie_loop > 5: helpers.test_error("Detected session cookie loop.") elif ('description' in result['content'] and re.match( r'.*cookie.*', result['content']['description'], re.I)): # Retry if: # "Authorization failed: No session found for cookie" # "Authorization failed: No session cookie provided" self.session_cookie_loop += 1 helpers.log( "It appears the session cookie has expired." " Requesting new session cookie.") self.request_session_cookie() # helpers.sleep(2) # Re-run command result = self._http_request(*args, **kwargs) else: # Error, possibly due to "invalid user/password combination" or others. helpers.test_error("Unable to create session cookie.") else: self.session_cookie_loop = 0 break return result
def cli_boot_factory_default_and_first_boot(self, node, reboot_sleep=60, **kwargs): """ Call 'cli boot factory default' to put device in first-boot mode. Then call 'cli_add_first_boot' to configure the device. """ do_factory_boot = True do_first_boot = True if not helpers.is_controller(node): helpers.test_error("Node must be a controller ('c1', 'c2').") if do_factory_boot: self.cli_boot_factory_default(node) helpers.log("Sleeping for %s seconds before first boot setup" % reboot_sleep) helpers.sleep(reboot_sleep) if do_first_boot: return self.cli_add_first_boot(node, **kwargs)
def bash_ping(self, node, dest_ip=None, dest_node=None, *args, **kwargs): """ Perform a ping from the shell. Returns the loss percentage - 0 - 0% loss - 100 - 100% loss Inputs: - node: The device name as defined in the topology file, e.g., 'c1', 's1', etc. - dest_ip: Ping this destination IP address - dest_node Ping this destination node ('c1', 's1', etc) - source_if: Source interface - count: Number of ping packets to send - ttl: IP Time-to-live Example: | ${lossA} = | Bash Ping | h1 | 10.192.104.1 | source_if=eth1 | | ${lossB} = | Bash Ping | node=master | dest_node=s1 | | => - ${lossA} = 0 - ${lossB} = 100 See also Controller.cli ping. """ t = test.Test() n = t.node(node) if not dest_ip and not dest_node: helpers.test_error("Must specify 'dest_ip' or 'dest_node'") if dest_ip and dest_node: helpers.test_error("Specify 'dest_ip' or 'dest_node' but not both") if dest_ip: dest = dest_ip if dest_node: dest = t.node(dest_node).ip() status = helpers._ping(dest, node_handle=n, mode='bash', *args, **kwargs) return status
def cli_reload(self, node): """ Reloads (aka reboots) a controller - BigTap, BigWire, BVS, or SwitchLight. """ t = test.Test() n = t.controller(node) platform = n.platform() helpers.log("Reloading '%s' (platform=%s)" % (n.name(), n.platform())) if helpers.is_bigwire(platform) or helpers.is_bigtap(platform): self._boot_bigtap_bigwire(node) elif helpers.is_bvs(platform): self._boot_bvs(node) elif helpers.is_switchlight(platform): self._boot_switchlight(node) else: helpers.test_error("Reload does not recognize platform '%s'" % platform) helpers.log("Device '%s' has rebooted" % n.name())
def console(self, driver=None, force_reconnect=False, expect_console_banner=False): if self.dev_console and not force_reconnect: return self.dev_console else: # helpers.log("Connecting to console for node '%s'" % self.name()) pass super(SwitchNode, self).console(driver) if self._console_info['type'] == 'telnet': # For telnet console, requirements are an IP address and a port # number. self.dev_console = devconf.SwitchDevConf( name=self.name() + "_console", host=self._console_info['ip'], port=self._console_info['port'], user=self._console_info['user'], password=self._console_info['password'], protocol=self._console_info['protocol'], console_info=self._console_info, debug=self.dev_debug_level) else: helpers.test_error("Unsupported console type '%s'" % self._console_info['type']) if expect_console_banner: self._match_console_banner() # FIXME!!! The code below is not working. Figure out why... # if self._console_info['driver']: # helpers.log("Setting devconf driver for console to '%s'" # % self._console_info['driver']) # self.dev_console.conn.set_driver(self._console_info['driver']) return self.dev_console
def node_id(self): """ Node-id is mainly supported for BVS platform but that may change over time. For now, all derived nodes should simply return None. For BVS, get the node-id for the specified node. The REST 'show cluster' API has 'local-node-id' which is the node-id for the node we want. Input: Node name (e.g., 'master', 'c1', 'c2', etc.) Output: Integer value for the node-id """ node = self.name() n = self.t.controller(node) if not helpers.is_bvs(n.platform()): return None count = 0 while (True): try: url = '/api/v1/data/controller/cluster' content = n.rest.get(url)['content'] nodeid = content[0]['status']['local-node-id'] helpers.log("'%s' has local-node-id %s" % (node, nodeid)) break except (KeyError): if (count < 5): helpers.warn("'%s' KeyError while retrieving" " local-node-id. Sleeping for 10 seconds." % node) helpers.sleep(10) count += 1 else: helpers.test_error("'%s' KeyError while retrieving" " local-node-id." % node) return nodeid
def switchLight_image_install(self, node, newSwitchFlag="true", switchIp=None, netMask=None, gatewayIp=None ): t = test.Test() switch = t.switch(node) user = "******" password = "******" console_ip = t.params(node, "console_ip") console_port = t.params(node, "console_port") if not switchIp: helpers.test_error("You must specify switchIp") if not netMask: helpers.test_error("You must specify netMask") if not gatewayIp: helpers.test_error("You must specify gatewayIp") swLightUrl = "setenv sl_url 'http://10.192.74.102/export/switchlight/autobuilds/master/latest.switchlight-powerpc-release.all.installer'" swLightenv = "setenv sl_ip ${ipaddr}::${gatewayip}:${netmask}::eth0:off" swLightonie = "setenv onie_debugargs install_url=${sl_url} ip=${sl_ip}" swLightImagePath = "wget http://10.192.74.102/export/switchlight/autobuilds/master/latest.switchlight-powerpc-internal-t5.swi" swLightFlash = "echo \"SWI=flash2:latest.switchlight-powerpc-internal-t5.swi\" >/mnt/flash/boot-config" helpers.log("IN HERE 1") #tn= telnetlib.Telnet(console_ip,console_port) # is false (${newSwitchflag}, msg="This is not a new Switch"): tn= telnetlib.Telnet(console_ip,console_port) helpers.log("IN HERE newSwitchFalse") tn.read_until("login:"******"\r\n") helpers.log("IN HERE newSwitchFalse") tn.read_until("password:"******"\r\n") tn.read_until("#", 3) # is true (${newSwitchflag}, msg="This is new Switch"): # tn= telnetlib.Telnet(console_ip,console_port) # helpers.log("IN HERE newSwitchTrue") # tn.read_until("#", 3) helpers.log("Reboot the switch and wait 30 ") tn.write("reboot" + "\r\n") #sleep 30 tn.read_until("Hit any key to stop autoboot:", 30) tn.write("\r\n") tn.read_until("=>", 3) helpers.log("afterautoboot") tn.read_until("=>", 5) tn.write("setenv ipaddr switchIp" + "\r\n") tn.read_until("=>", 5) tn.write("setenv netmask netMask" + "\r\n") tn.read_until("=>", 5) tn.write("setenv gatewayip gatewayIp" + "\r\n") tn.read_until("=>", 5) tn.write("setenv serverip 10.192.74.102" + "\r\n") tn.read_until("=>", 5) tn.write("saveenv" + "\r\n") tn.read_until("=>", 5) tn.write(swLightUrl + "\r\n") tn.read_until("=>", 5) tn.write(swLightenv + "\r\n") tn.read_until("=>", 5) tn.write(swLightonie + "\r\n") tn.read_until("=>", 5) tn.write("run onie_bootcmd" + "\r\n") tn.read_until("=>", 5) tn.write("boot" + "\r\n") #sleep 10 tn.read_until("Press Control-C now to enter loader shell", 30) tn.write("\x03" + "\r\n") helpers.log("IN HERE loadershell") tn.read_until("loader#", 10) tn.write("#inloadershell" + "\r\n") tn.read_until("loader#", 3) tn.write("netconf" + "\r\n") tn.read_until("Which interface (blank for ma1)?", 3) tn.write("ma1" + "\r\n") tn.read_until("IP address (/prefix optional for v4)?", 3) tn.write("switchIp/18" + "\r\n") tn.read_until("Default gateway IP address (blank for none)?", 3) tn.write("gatewayIp" + "\r\n") tn.read_until("DNS IP address (blank for none)?", 3) tn.write("10.192.3.1" + "\r\n") tn.read_until("DNS default domain (blank for none)?", 3) tn.write("bigswitch.com" + "\r\n") helpers.log("#DoneLoader#") tn.read_until("#", 10) tn.write("cd /mnt/flash2" + "\r\n") tn.read_until("#", 10) tn.write(swLightImagePath + "\r\n") tn.read_until("#", 10) tn.write(swLightFlash + "\r\n") tn.read_until("#", 10) tn.write("boot" + "\r\n") helpers.log("AfterUpgradeLogging") tn.read_until("login:"******"\r\n") tn.read_until("password:"******"\r\n") tn.read_until("#", 3) helpers.log("AfterUpgradeLogged") tn.write("#DONE#" + "\r\n") tn.read_until("#", 5) tn.write("uname -a" + "\r\n") tn.read_until("#", 5) tn.write("exit" + "\r\n") #print tn.read_all() tn.close()
def cli_upgrade_image(self, node=None, package=None, timeout=600, sleep_time=600): ''' Objective: - Execute CLI commands to download given upgrade package to Master (and Slave if exists) Controllers and upgrade them Input: | `package` | URL to the upgrade package | | `node` | Node to be upgraded. Leave empty to upgrade all nodes in your topology | | `timeout` | Timeout (in seconds) for "upgrade" command to be execute | | `sleep` | Time (in seconds) of sleep after upgrade, before next actions | Return Value: - True if configuration is successful - False otherwise ''' t = test.Test() if not package: helpers.test_error("You must specify a package name") if not node: # assume all controllers if node is not specified node_handles = t.controllers() controller_qty = len(t.controllers()) else: node_handles = [t.controller(node)] controller_qty = 1 helpers.log("Number of controllers %s" % controller_qty) if controller_qty > 2 or controller_qty < 1: helpers.test_log( "More than two controllers or no controller configured") return False for i in range(0, controller_qty): try: if controller_qty > 1: n = t.controller('slave') else: n = node_handles[0] helpers.log("No %s : Upgrade '%s' to image '%s'" % (i, n.name(), package)) n.bash("cd /home/images/") n.bash("sudo rm *") n.bash("sudo wget %s" % package) n.bash("exit") helpers.log("Image downloaded successfully") n.enable('enable') n.send("upgrade") n.expect(r"\(yes to continue\)") n.send("yes") n.expect(r"Password:"******"adminadmin", timeout=timeout) n.send("reload") n.expect(r"Confirm Reload \(yes to continue\)") n.send("yes") helpers.sleep(sleep_time) except: helpers.test_log("Output: %s" % n.cli_content()) return False return True
def _http_request(self, url, verb='GET', data=None, session=None, quiet=0, save_last_result=True, log_level='info'): """ Generic HTTP request for POST, GET, PUT, DELETE, etc. data is a Python dictionary. """ # helpers.log("url: '%s'" % url) # helpers.log("verb: '%s'" % verb) # helpers.log("data: '%s'" % data) if url is None: url = self.base_url if url is None: helpers.environment_failure("Problem locating base URL.") headers = self.default_header if session: headers['Cookie'] = 'session_cookie=%s' % session elif self.session_cookie: headers['Cookie'] = 'session_cookie=%s' % self.session_cookie if helpers.not_quiet(quiet, [2, 5]): helpers.log("'%s' RestClient: %s %s" % (self._name, verb, url), level=5, log_level=log_level) helpers.log("'%s' Headers = %s" % (self._name, helpers.to_json(headers)), level=5, log_level=log_level) if data: helpers.log("'%s' Data = %s" % (self._name, helpers.to_json(data)), level=5, log_level=log_level) prefix_str = '%s %s' % (self.name(), verb.lower()) data_str = '' if data: data_str = ' %s' % helpers.to_json(data, is_raw=True) if len(data_str) > 50: # If data is more than 50 chars long, then prettify JSON data_str = ' %s' % helpers.to_json(data) # helpers.bigrobot_devcmd_write("%-9s: %s%s\n" # % (prefix_str, url, data_str)) if helpers.is_dict(data) or helpers.is_list(data): formatted_data = helpers.to_json(data) else: formatted_data = data resp, content = self.http.request(url, verb, body=formatted_data, headers=headers) code = resp['status'] if content: python_content = helpers.from_json(content) else: python_content = {} result = {'content': python_content} result['http_verb'] = verb result['http_data'] = formatted_data result['status_code'] = int(code) result['request_url'] = url if save_last_result: self.last_result = result if helpers.not_quiet(quiet, [1, 5]): self.log_result(result=result, level=6, log_level=log_level) # ATTENTION: RESTclient will generate an exception when the # HTTP status code is anything other than: # - 200-300 # - 200 (OK) # - 201 (Created) # - 202 (Accepted) # - 401 (Authen/session cookie issue) # - 409 (List element already exists) # # Reference: # http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml if code in RestClient.http_codes: result['status_descr'] = RestClient.http_codes[code] elif int(code) in range(200, 300): # Success (BSN-specific) result['status_descr'] = RestClient.http_codes['200'] else: result['status_descr'] = RestClient.http_codes['unknown'] result['success'] = False # As per https://github.com/bigswitch/floodlight/commit/a432f1b501640474b8bf6cb87a07dcbf28df8691 if int(code) in range(200, 300): result['success'] = True elif int(code) == 401: # Session cookie has expired. This requires exception handling # by BigRobot pass elif int(code) == 409: # On POST when "List element already exists" result['success'] = True else: helpers.test_error("REST call failed with status code %s" % code) return result
def cli_add_first_boot( self, node, ip_address=None, netmask='', gateway='', dns_server='', dns_search='', ntp_server='', hostname='mycontroller', cluster_name='mycluster', cluster_descr='', admin_password='******', platform='bvs', ): """ First boot setup fpr BVS - It will then connect to the console to complete the first-boot configuration steps (call 'cli add first boot'). """ if platform != 'bvs': helpers.test_error("Only 'bvs' platform is supported") t = test.Test() n = t.node(node) if not ip_address: ip_address = n.ip() helpers.log("Getting the console session for '%s'" % node) n_console = n.console() _ = """ Note: Below is the basic first boot question/answer output. root@qa-kvm-32:~# virsh console vui-bvs Connected to domain vui-bvs Escape character is ^] Big Virtual Switch Appliance 2.0.5-SNAPSHOT (bvs master #1223) Log in as 'admin' to configure controller login: admin <=== Last login: Mon Mar 17 20:28:31 UTC 2014 from 10.192.123.117 on pts/0 The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. <clear screen> This product is governed by an End User License Agreement (EULA). You must accept this EULA to continue using this product. You can view this EULA by typing 'View', or from our website at: http://www.bigswitch.com/eula Do you accept the EULA for this product? (Yes/No/View) [Yes] > Yes <=== Running system pre-check Found eth0 Found 2 CPU cores Found 2.00 GB of memory Finished system pre-check Starting first-time setup Local Node Configuration ------------------------ Password for emergency recovery user > bsn <=== Retype Password for emergency recovery user > bsn <=== Please choose an IP mode: [1] Manual [2] Automatic via DHCP > 1 <=== IP address [0.0.0.0/0] > 10.192.104.2 <=== CIDR prefix length [24] > 18 <=== Default gateway address (Optional) > 10.192.64.1 <=== DNS server address (Optional) > 10.192.3.1 <=== DNS search domain (Optional) > bigswitch.com <=== Hostname > blah <=== Controller Clustering --------------------- Please choose a cluster option: [1] Start a new cluster [2] Join an existing cluster > 1 <=== Cluster name > bleh <=== Cluster description (Optional) > [enter] <=== Administrator password for cluster > adminadmin <=== Retype Administrator password for cluster > adminadmin <=== System Time ----------- Enter NTP server [0.bigswitch.pool.ntp.org] > [enter] <=== Menu ---- Please choose an option: [ 1] Apply settings [ 2] Reset and start over [ 3] Update Emergency Recovery Password (***) [ 4] Update IP Auto/Manual (Manual) [ 5] Update Local IP Address (10.192.104.2) [ 6] Update CIDR Prefix Length (18) [ 7] Update Gateway (10.192.64.1) [ 8] Update DNS Server (10.192.3.1) [ 9] Update DNS Search Domain (bigswitch.com) [10] Update Hostname (blah) [11] Update Cluster Option (Start a new cluster) [12] Update Cluster Name (bleh) [13] Update Cluster Description (<none>) [14] Update Cluster Admin Password (***) [15] Update NTP Server (0.bigswitch.pool.ntp.org) [1] > 1 <=== [Stage 0] Initializing system [Stage 1] Configuring controller Waiting for network configuration IP address on eth0 is 10.192.104.2 Generating cryptographic keys Retrieving time from NTP server 0.bigswitch.pool.ntp.org [Stage 2] Configuring cluster Cluster configured successfully. Current node ID is 3146 All cluster nodes: Node 3146: 10.192.104.2:6642 First-time setup is complete! Press enter to continue > [enter] <=== Big Virtual Switch Appliance 2.0.5-SNAPSHOT (bvs master #1223) Log in as 'admin' to configure blah login: admin <=== Password: ***** <=== Last login: Mon Mar 17 19:01:17 UTC 2014 on ttyS0 Big Virtual Switch Appliance 2.0.5-SNAPSHOT (bvs master #1223) Logged in as admin, 2014-03-17 20:24:20.843000 UTC, auth from blah blah> """ n_console.expect(r'Escape character.*[\r\n]') n_console.send('') # press <Enter> and expect to see the login prompt # We might be in midst of a previously failed first boot setup. # Interrupt it (Control-C) and press <Enter> to log out... n_console.send(helpers.ctrl('c')) helpers.sleep(2) n_console.send('') n_console.expect(helpers.regex_bvs()) n_console.expect(r'login:'******'admin') # Need to enable developer mode to use DHCP option. Magic string # to enable it is 'dhcp'. n_console.expect(r'Do you accept the EULA.* > ') n_console.send('dhcp') n_console.expect(r'Developer.* mode enabled.*') # The "real" EULA n_console.expect(r'Do you accept the EULA.* > ') n_console.send('Yes') n_console.expect(r'Local Node Configuration') n_console.expect(r'Password for emergency recovery user > ') n_console.send('bsn') n_console.expect(r'Retype Password for emergency recovery user > ') n_console.send('bsn') n_console.expect(r'Please choose an IP mode:.*[\r\n]') n_console.expect(r'> ') n_console.send('1') # Manual n_console.expect(r'IP address .* > ') n_console.send(ip_address) if not re.match(r'.*/\d+', ip_address): # Send netmask if IP address doesn't contain prefix length n_console.expect(r'CIDR prefix length .* > ') n_console.send(netmask) n_console.expect(r'Default gateway address .* > ') n_console.send(gateway) n_console.expect(r'DNS server address .* > ') n_console.send(dns_server) n_console.expect(r'DNS search domain .* > ') n_console.send(dns_search) n_console.expect(r'Hostname > ') n_console.send(hostname) n_console.expect(r'Controller Clustering') n_console.expect(r'> ') n_console.send('1') # Start a new cluster n_console.expect(r'Cluster name > ') n_console.send(cluster_name) n_console.expect(r'Cluster description .* > ') n_console.send(cluster_descr) n_console.expect(r'Administrator password for cluster > ') n_console.send(admin_password) n_console.expect(r'Retype .* > ') n_console.send(admin_password) n_console.expect(r'System Time') n_console.expect(r'Enter NTP server .* > ') n_console.send(ntp_server) n_console.expect(r'Please choose an option:.*[\r\n]') n_console.expect(r'\[1\] > ') n_console.send('1') # Apply settings n_console.expect(r'Initializing system.*[\r\n]') n_console.expect(r'Configuring controller.*[\r\n]') n_console.expect(r'Configuring cluster.*[\r\n]') n_console.expect(r'First-time setup is complete.*[\r\n]') n_console.expect(r'Press enter to continue > ') n_console.send('') helpers.log("Closing console connection for '%s'" % node) n.console_close() helpers.sleep(3) # Sleep for a few seconds just in case... # Check that controller is now pingable. # First remove the prefix from the IP address. new_ip_address = re.sub(r'/\d+$', '', ip_address) loss = helpers.ping(new_ip_address) if loss < 50: helpers.log("Node '%s' has survived first-boot!" % node) return True else: return False
def console(self, driver=None, force_reconnect=False, expect_console_banner=False): if self.dev_console and not force_reconnect: return self.dev_console else: # helpers.log("Connecting to console for node '%s'" % self.name()) pass super(ControllerNode, self).console(driver) helpers.log("'%s' console type: %s" % (self.name(), self._console_info['type'])) if self._console_info['type'] == 'telnet': # For telnet console, requirements are an IP address and a port # number. self.dev_console = devconf.ControllerDevConf( name=self.name() + "_console", host=self._console_info['ip'], port=self._console_info['port'], user=self._console_info['user'], password=self._console_info['password'], protocol=self._console_info['protocol'], console_info=self._console_info, debug=self.dev_debug_level) elif self._console_info['type'] == 'libvirt': # For libvirt console, requirements are an IP address (of the # KVM server) and the libvirt VM name (libvirt_vm_name). We will # first SSH to the KVM server, then execute 'virsh console <name>'. # # Note: We're using ControllerDevConf even though the libvirt # server is Ubuntu. This is because once we get on the controller # console, we want to be able to issue commands in different # modes: cli, enable, config, bash, etc. self.dev_console = devconf.ControllerDevConf( name=self.name() + "_console", host=self._console_info['ip'], port=self._console_info['port'], user=self._console_info['user'], password=self._console_info['password'], protocol=self._console_info['protocol'], console_info=self._console_info, debug=self.dev_debug_level) else: helpers.test_error("Unsupported console type '%s'" % self._console_info['type']) if self._console_info['type'] == 'libvirt': self.dev_console.send("virsh console %s" % self._console_info['libvirt_vm_name']) if expect_console_banner: self._match_console_banner() # FIXME!!! The code below is not working. Figure out why... # if self._console_info['driver']: # helpers.log("Setting devconf driver for console to '%s'" # % self._console_info['driver']) # self.dev_console.conn.set_driver(self._console_info['driver']) return self.dev_console